Dapperでマルチマッピングが機能しない

c# dapper multi-mapping

質問

Dapperと一緒に遊んで、これまでのところ興味深い結果にとても満足しています!

しかし今、私の次のシナリオは、 StudentテーブルとAddressテーブルの2つのテーブルからデータを読み込むことです。

StudentテーブルにはStudentID (INT IDENTITY)主キーがあり、 AddressにはAddressID (INT IDENTITY)ます。 StudentAddressテーブルにリンクするAddressIDというFKも持っています。

私の考えは、興味のあるプロパティを持つテーブルごとに1つのクラスを2つ作成することでした。さらに、C#のStudentクラスにAddress型のPrimaryAddressプロパティを配置しました。

私はその後、単一のクエリで学生と住所の両方のデータを取得しようとしました - 私はGithubページで与えられたサンプルを模倣します

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

ここでは、 PostUserが取得され、そのPostの所有者がユーザに設定されます。返される型はPost -correct?

私のコードでは、一般的なQuery拡張メソッドの2つのパラメータを定義します。最初にStudentを返す必要があり、 Addressを2番目に指定して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を1つのメソッドでパイプします。したがって、何かが失敗した場合、6つのパラメタになります。パズルのもう一つの部分は、私が追加した超柔軟な分割を許可していないということでした。

splitOnパラメータはデフォルトで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();


ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ