無法在Dapper中使用多映射

c# dapper multi-mapping

和Dapper一起玩,我對目前的結果非常滿意 - 很有趣!

但現在,我的下一個場景是從兩個表中讀取數據 - StudentAddress表。

Student表具有StudentID (INT IDENTITY)的主鍵, Address具有AddressID (INT IDENTITY)Student還有一個名為AddressID的FK鏈接到Address表中。

我的想法是創建兩個類,每個表一個,具有我感興趣的屬性。另外,我將一個類型為AddressPrimaryAddress屬性放到我在C#中的Student類中。

然後我嘗試在單個查詢中檢索學生和地址數據 - 我模仿Github頁面上給出的樣本:

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

在這裡,檢索PostUser ,並將帖子的所有者設置為用戶 - 返回的類型是Post -correct?

所以在我的代碼中,我為通用的Query擴展方法定義了兩個參數 - 一個Student作為第一個應該返回的,一個Address作為第二個,它將存儲在student實例上:

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種類型參數的重載...

一般承認的答案

這將是因為我更改了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個參數中。另一個難題是我不允許一些超級靈活的分裂,我剛才補充說。

注意, splitOn參數將默認為Id ,這意味著它將使用名為idId的列作為第一個對象邊界。但是,如果您需要具有不同名稱的多個主鍵的邊界,例如“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();


許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因