Dapperでのマルチマッピングの正しい使い方

dapper

質問

私は、ProductItemsと関連するCustomersのリストを返すために、dapperのMultimapping機能を使用しようとしています。

[Table("Product")]
public class ProductItem
{
    public decimal ProductID { get; set; }        
    public string ProductName { get; set; }
    public string AccountOpened { get; set; }
    public Customer Customer { get; set; }
} 

public class Customer
{
    public decimal CustomerId { get; set; }
    public string CustomerName { get; set; }
}

私の大まかなコードは次の通りです

var sql = @"select * from Product p 
            inner join Customer c on p.CustomerId = c.CustomerId 
            order by p.ProductName";

var data = con.Query<ProductItem, Customer, ProductItem>(
    sql,
    (productItem, customer) => {
        productItem.Customer = customer;
        return productItem;
    },
    splitOn: "CustomerId,CustomerName"
);

これは正常に動作しますが、splitOnパラメータにすべての顧客プロパティを返すために完全な列リストを追加する必要があるようです。 "CustomerName"を追加しない場合、nullを返します。マルチマッピング機能の中核機能を理解していませんか?私は毎回列名の完全なリストを追加する必要はありません。

受け入れられた回答

私はちょうどうまく動作するテストを実行しました:

var sql = "select cast(1 as decimal) ProductId, 'a' ProductName, 'x' AccountOpened, cast(1 as decimal) CustomerId, 'name' CustomerName";

var item = connection.Query<ProductItem, Customer, ProductItem>(sql,
    (p, c) => { p.Customer = c; return p; }, splitOn: "CustomerId").First();

item.Customer.CustomerId.IsEqualTo(1);

splitOnパラメーターを分割点として指定する必要があります。デフォルトはIdです。スプリットポイントが複数ある場合は、コンマで区切ってリストに追加する必要があります。

レコードセットが次のようになっているとします。

ProductID | ProductName | AccountOpened | CustomerId | CustomerName 
---------------------------------------   -------------------------

Dapperは、この順序で列を2つのオブジェクトに分割する方法を知る必要があります。 splitOn: CustomerIdな外観は、得意先がCustomerId列から開始することを示します。したがって、 splitOn: CustomerId

何らかの理由で基になるテーブルの列の順序が反転した場合は、 大きな注意点があります。

ProductID | ProductName | AccountOpened | CustomerName | CustomerId  
---------------------------------------   -------------------------

splitOn: CustomerIdはnullの顧客名になります。

分割点としてCustomerId,CustomerNameを指定すると、結果セットを3つのオブジェクトに分割しようとしていると仮定します。最初は最初から開始し、2番目はCustomerId 、3番目はCustomerNameで開始します。


人気のある回答

私たちのテーブルはあなたのものと同じように名前が付けられています。ここでは、 "select *"操作を使って "CustomerID"のようなものが2回返されるかもしれません。したがって、Dapperは仕事をしていますが、列が次のようになっているため、(おそらく)あまりにも早く分裂しています。

(select * might return):
ProductID,
ProductName,
CustomerID, --first CustomerID
AccountOpened,
CustomerID, --second CustomerID,
CustomerName.

これにより、spliton:パラメータはあまり役に立ちません。特に、カラムが返される順序が不明な場合は特に注意してください。もちろん、カラムを手動で指定することもできますが、2017年であり、基本オブジェクト取得のためにこれを行うことはめったにありません。

私たちがやっていることは何年もの間何千ものクエリを処理していて、Idのエイリアスを使用しているだけで、(Dapperのデフォルトの 'Id'を使って)splitonを決して指定しません。

select 
p.*,

c.CustomerID AS Id,
c.*

...ボイラー! DapperはデフォルトでIdにのみ分割され、そのIdはすべてのCustomer列の前に発生します。もちろん、結果セットに余分な列が追加されますが、これは、どの列がどのオブジェクトに属しているかを正確に把握するための追加されたユーティリティのオーバーヘッドを最小限に抑えます。そしてあなたはこれを簡単に拡張することができます。住所と国の情報が必要ですか?

select
p.*,

c.CustomerID AS Id,
c.*,

address.AddressID AS Id,
address.*,

country.CountryID AS Id,
country.*

何よりも、どのオブジェクトがどの列に関連付けられているかをSQLの最小限の量で明確に示しています。ダッパーは残りをする。



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