在Dapper中正確使用Multimapping

dapper

我正在嘗試使用dapper的Multimapping功能來返回ProductItems和相關Customers的列表。

[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個對象。粗略的外觀顯示客戶從CustomerId列開始,因此splitOn: CustomerId

這裡有一個很大的警告,如果基礎表中的列排序由於某種原因被翻轉:

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

splitOn: CustomerId將導致null客戶名稱。

如果將CustomerId,CustomerName指定為拆分點,則dapper假定您嘗試將結果集拆分為3個對象。首先從CustomerId開始,第二個在CustomerId開始,第三個在CustomerName


熱門答案

我們的表名稱與您的表格類似,其中“CustomerID”之類的內容可能會使用“select *”操作返回兩次。因此,Dapper正在做它的工作,但只是過早地(可能)分裂,因為列將是:

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

這使得spliton:參數不那麼有用,特別是當你不確定返回列的順序時。當然你可以手動指定列......但它是2017年,我們很少再這樣做了基本對象獲取。

我們所做的,多年來為數以千計的查詢工作得很好,只是使用了Id的別名,而且從不指定spliton(使用Dapper的默認'Id')。

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哪些列與哪個對象相關聯。 Dapper完成其餘的工作。



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