无法在Dapper中使用多映射

和Dapper一起玩,我对目前的结果非常满意 – 很有趣!

但现在,我的下一个场景是从两个表中读取数据 – StudentAddress表。

Student表具有StudentID (INT IDENTITY)的主键, Address具有AddressID (INT IDENTITY)Student还有一个名为AddressID的FK链接到Address表中。

我的想法是创建两个类,每个表一个,具有我感兴趣的属性。另外,我将一个类型为AddressPrimaryAddress属性放到我在C#中的Student类中。

然后我尝试在单个查询中检索学生和地址数据 – 我模仿Github页面上给出的样本:

 var data = connection.Query(sql, (post, user) => { post.Owner = user; }); var post = data.First(); 

在这里,检索PostUser ,并将post的所有者设置为用户 – 返回的类型是Post -correct?

所以在我的代码中,我为通用的Query扩展方法定义了两个参数 – 一个Student作为第一个应该返回的,一个Address作为第二个,它将存储在student实例上:

 var student = _conn.Query ("SELECT s.*, a.* FROM dbo.Student s INNER JOIN dbo.Address a ON s.AddressID = a.AddressID WHERE s.StudentenID = @Id", (stu, adr) => { stu.PrimaryAddress = adr; }, new { Id = 4711 }); 

麻烦的是 – 我在Visual Studio中遇到错误:

使用generics方法’Dapper.SqlMapper.Query(System.Data.IDbConnection,string,System.Func,dynamic,System.Data.IDbTransaction,bool,string,int?,System.Data.CommandType?)’需要6个类型参数

我真的不明白为什么Dapper坚持使用这种带有6种类型参数的重载…

这将是因为我更改了API并忘记更新文档,我更正了错误。

请务必查看Tests.cs以获取完整的最新规范。

特别是旧的API用来接受Action来执行映射,麻烦的是它感觉既武断又不灵活。 您无法完全控制返回类型。 新API采用Func 。 因此,您可以控制从映射器返回的类型,它不需要是映射类型。

我只是围绕多映射加强了一些额外的灵活性,这个测试应该说清楚:

 class Person { public int PersonId { get; set; } public string Name { get; set; } } class Address { public int AddressId { get; set; } public string Name { get; set; } public int PersonId { get; set; } } class Extra { public int Id { get; set; } public string Name { get; set; } } public void TestFlexibleMultiMapping() { var sql = @"select 1 as PersonId, 'bob' as Name, 2 as AddressId, 'abc street' as Name, 1 as PersonId, 3 as Id, 'fred' as Name "; var personWithAddress = connection.Query> (sql, (p,a,e) => Tuple.Create(p, a, e), splitOn: "AddressId,Id").First(); personWithAddress.Item1.PersonId.IsEqualTo(1); personWithAddress.Item1.Name.IsEqualTo("bob"); personWithAddress.Item2.AddressId.IsEqualTo(2); personWithAddress.Item2.Name.IsEqualTo("abc street"); personWithAddress.Item2.PersonId.IsEqualTo(1); personWithAddress.Item3.Id.IsEqualTo(3); personWithAddress.Item3.Name.IsEqualTo("fred"); } 

Dapper通过单个方法管理所有多映射API,因此如果出现故障,它将最终出现在6个参数中。 另一个难题是我不允许一些超级灵活的分裂,我刚才补充说。

注意, splitOn参数将默认为Id ,这意味着它将使用名为idId的列作为第一个对象边界。 但是,如果您需要具有不同名称的多个主键的边界,例如“3路”多映射,您现在可以传入逗号分隔列表。

因此,如果我们要解决上述问题,可能以下方法可行:

  var student = _conn.Query ("SELECT s.*, a.* FROM dbo.Student s INNER JOIN dbo.Address a ON s.AddressID = a.AddressID WHERE s.StudentenID = @Id", (stu, adr) => { stu.PrimaryAddress = adr; return stu;}, new { Id = 4711 }, splitOn: "AddressID").FirstOrDefault();