mar*_*c_s 17 c# dapper multi-mapping
和Dapper一起玩,我对目前的结果非常满意 - 很有趣!
但现在,我的下一个场景是从两个表中读取数据 -  a Student和Address表.
Student表有一个主键StudentID (INT IDENTITY),Address有一个AddressID (INT IDENTITY).Student还有一个名为AddressID链接到Address表中的FK .
我的想法是创建两个类,每个表一个,具有我感兴趣的属性.另外,我在C#中将PrimaryAddress类型的属性Address放到我的Student类中.
然后我尝试在单个查询中检索学生和地址数据 - 我模仿Github页面上给出的样本:
var data = connection.Query<Post, User>(sql, (post, user) => { post.Owner = user; });
var post = data.First();
在这里,检索a Post和a User,并将帖子的所有者设置为用户 - 返回的类型是Post- 正确吗?
所以在我的代码中,我为通用Query扩展方法定义了两个参数- Student作为第一个应该返回的参数,Address第二个参数将存储到学生实例中:
var student = _conn.Query<Student, Address>
                  ("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中遇到错误:
使用泛型方法'Dapper.SqlMapper.Query(System.Data.IDbConnection,string,System.Func,dynamic,System.Data.IDbTransaction,bool,string,int?,System.Data.CommandType?)'需要6个类型参数
我真的不明白为什么Dapper坚持使用这种带有6种类型参数的重载...
Sam*_*ron 22
那是因为我更改了API并忘记更新文档,我更正了错误.
请务必查看Tests.cs以获取完整的最新规范.
特别是,旧的API过去常常用来Action<T,U>执行映射,麻烦的是它感觉既武断又不灵活.您无法完全控制返回类型.新的API采用了Func<T,U,V>.因此,您可以控制从映射器返回的类型,它不需要是映射类型.
我只是围绕多映射加强了一些额外的灵活性,这个测试应该说清楚:
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<Person, Address, Extra, Tuple<Person, Address,Extra>>
        (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个参数中.另一个难题是我没有允许一些超级灵活的分裂,我刚才补充说.
注意,splitOnparam将默认为Id,这意味着它将采用一个被调用的列id或Id作为第一个对象边界.但是,如果您需要具有不同名称的多个主键的边界,例如"3路"多映射,您现在可以传入逗号分隔列表.
因此,如果我们要解决上述问题,可能以下方法可行:
 var student = _conn.Query<Student,Address,Student>
              ("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();
| 归档时间: | 
 | 
| 查看次数: | 15478 次 | 
| 最近记录: |