Dapper.netを使用したマルチマッピングクエリでの予期しない動作

asp.net c# dapper mapping

質問

私はただDapper.netを見て始め、いくつかの異なるクエリを試しています。そのうちの1つは、私が期待していない奇妙な結果を生み出しています。

私は2つのテーブルを持っています - PhotosPhotoCategoriesCategoryID関連しています

写真のテーブル

PhotoId (PK - int)  
CategoryId (FK - smallint)  
UserId (int)

PhotoCategoriesテーブル

CategoryId (PK - smallint)  
CategoryName (nvarchar(50))

私の2つのクラス:

public class Photo
{
    public int PhotoId { get; set; }
    public short CategoryId { get; set; }
    public int UserId { get; set; }
    public PhotoCategory PhotoCategory { get; set; }
}

public class PhotoCategory
{
    public short CategoryId { get; set; }
    public string CategoryName { get; set; }
{

私は、マルチマップを使用して、関連するPhotoCategoryインスタンスが設定された状態で、 Photoインスタンスを返したいと考えています。

var sql = @"select p.*, c.* from Photos p inner 
            join PhotoCategories c 
            on p.CategoryID = c.CategoryID where p.PhotoID = @pid";

cn.Open();
var myPhoto = cn.Query<Photo, PhotoCategory, Photo>(sql, 
               (photo, photoCategory) => { photo.PhotoCategory = photoCategory; 
                                           return photo; }, 
               new { pid = photoID }, null, true, splitOn: "CategoryID").Single();

これが実行されると、すべてのプロパティが(DBテーブルとオブジェクトの間で同じ名前であっても)読み込まれるわけではありません。

私が気付いたのは、私don't 「p。* etc.」を選択don'tと、私のSQLで、代わりに。

私はフィールドを明示します。

私は戻りたいEXCLUDING p.CategoryId 、その後、すべてが(私はselect文から除外されてきた写真のオブジェクトに対して明らかに区分を除く)が取り込まれます、クエリから。

しかし、私はそのフィールドをクエリに含めることができ、それをSQL内でクエリされた他のすべてのフィールドと同様に取り込むことができると期待します。

CategoryIdクラスのプロパティをPhotoクラスから除外でき、IDが必要なときは常にPhoto.PhotoCategory.CategoryIdを使用します。

しかし、場合によっては、Photoオブジェクトのインスタンスを取得したときに、 PhotoCategoryオブジェクトに値をPhotoCategoryたくない場合があります。

上記の現象が起こっている理由を知っていますか? Dapperのこれは正常ですか?

受け入れられた回答

私はちょうどこれのための修正を約束した:

    class Foo1 
    {
        public int Id;
        public int BarId { get; set; }
    }

    class Bar1
    {
        public int BarId;
        public string Name { get; set; }
    }

    public void TestMultiMapperIsNotConfusedWithUnorderedCols()
    {

        var result = connection.Query<Foo1,Bar1,
                      Tuple<Foo1,Bar1>>(
                         "select 1 as Id, 2 as BarId, 3 as BarId, 'a' as Name",
                         (f,b) => Tuple.Create(f,b), splitOn: "BarId")
                         .First();

        result.Item1.Id.IsEqualTo(1);
        result.Item1.BarId.IsEqualTo(2);
        result.Item2.BarId.IsEqualTo(3);
        result.Item2.Name.IsEqualTo("a");

    }

マルチマッパーは、 firstタイプのフィールドがあった場合、 secondタイプのフィールドがあると混乱していました...そして、...スプリットポイントとして使用されました。

これを克服するために、最初のタイプのどこにでもIdフィールドが表示されるようにします。説明する。

私たちは持っていると言う:

classes: A{Id,FooId} B{FooId,Name}
splitOn: "FooId"
data: Id, FooId, FooId, Name

分割の古い方法は、マッピングしていた実際の基底型を考慮していませんでした。だから...それはId => AFooId, FooId, Name => Bマップした

新しいメソッドは、 A小道具とフィールドを認識しています。ストリーム内のFooIdに最初に遭遇すると、 AFooIdというFooIdプロパティがあり、次回FooIdが見えるFooIdになるため、期待通りの結果が得られることが分かっているので、分割を開始しません。


人気のある回答

私はこの質問が古いことを知っていますが、私は誰かを2分節約すると思っていました。これは明らかな答えです。

すなわち:

SELECT
    user.Name, user.Email, user.AddressId As id, address.*
FROM 
    User user
    Join Address address
    ON user.AddressId = address.AddressId


ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow