dapper PropInfo用於從抽像類引用繼承的EntitySet的Setter為null

.net abstract-class c# dapper reflection

我試圖用一些精巧的查詢替換討厭的LINQ 2 SQL命中以改善性能。在這樣做時,我必須將一堆不同的對象編織在一起,以便創建保存ASN信息所需的所有信息所需的大對象。

我目前遇到的問題是抽像類Orders,這個類是由兩個單獨的類AutionOrder和MerchantOrder使用discriminator屬性實現的。

由於我不能使用dapper來創建一個抽像類的對象,而是使用其中一個公共類。然而,當它來構建它裡面的失敗的對象GetSettableProps它找到適當的DeclaringType不過GetProperty方法返回null時,它正在尋找這是一個性質internal或者是EntitySet 。我試圖使用t.BaseType.GetProperty以及p.GetAccessors().First().GetBaseDefinition().DeclaringType.GetProperty(p.Name).GetSetMethod(true)來破解它t.BaseType.GetProperty p.GetAccessors().First().GetBaseDefinition().DeclaringType.GetProperty(p.Name).GetSetMethod(true)沒有成功。

虛擬對象:

訂購

OrderID,Name,Address,RowVersion(internal),Shipments(EntitySet),OrderDetails(EntitySet),Customer(EntityRef)

裝船

ShipmentID,OrderID,TrackingNumber

訂單詳細信息

OrderDetailID,OrderID,Product,QTY,Price

顧客

客戶ID,姓名,

對於這個特定的SQL命中,我試圖抓住我需要的一些1對1關係映射。

SELECT o。* from Orders as o left join customer as c on o.CustomerID = c.CustomerID其中o.OrderID in(1,2,3);

這就是我用來使用小巧玲瓏的東西並讓它做到這一點:

using (var connection = new SqlConnection(_ConnectionString))
{
    connection.Open();
    results = connection.Query<MerchantOrder, MerchantCustomer, MerchantOrder>(sql.ToString(),
        (o, c) => { o.Customer = c; return o; },
        splitOn: "CustomerID");
}

如果我將Order改為公共類,這個問題就會消失,但這不是一個理想的副作用。嘗試為RowVersion設置propInfo時失敗 - 將其切換為public而不是internal解決了這個問題 - 儘管不是這樣。但是當它試圖為Order創建Shipments對象時失敗。當Order是公共類時,這一點都不是問題。

此外,我正在進行單獨的查詢以引入多對一的關係,例如將訂單發送到訂單和訂單的訂單詳細信息,並將結果標準化為正確的訂單對象。 MerchantOrder幾乎是一個沒有真正特殊邏輯的空類。這裡有區別的不同就是我們最終找到在實際SQL命中之前被抽像出來的CustomerID。

此外,我正在使用最新版本的dapper截至2011年12月20日。

我真的很喜歡小巧玲瓏,但這個問題讓我頭暈目眩 - 所以感謝你的幫助!

一般承認的答案

這是一個bug,現在已在trunk中修復:

public class AbstractInheritance
    {
        public abstract class Order
        {
            internal int Internal { get; set; }
            protected int Protected { get; set; }
            public int Public { get; set; }

            public int ProtectedVal { get { return Protected; } }
        }

        public class ConcreteOrder : Order
        {
            public int Concrete { get; set; }
        }
    }

    // http://stackoverflow.com/q/8593871
    public void TestAbstractInheritance() 
    {
        var order = connection.Query<AbstractInheritance.ConcreteOrder>("select 1 Internal,2 Protected,3 [Public],4 Concrete").First();

        order.Internal.IsEqualTo(1);
        order.ProtectedVal.IsEqualTo(2);
        order.Public.IsEqualTo(3);
        order.Concrete.IsEqualTo(4);

    }

一方面注意,根據設計,我們不在基類中設置私有字段或屬性。這種行為可能是神奇的,也不一致。

例如:

class A { private int a {get; set;} }
class B : A { private int a {get; set;} } 
class C: B {} 

// What should "select 1 a" do? Set it on A? Set it on B? Set it on Both? Set it on neither?

我們選擇“既不設置它”


熱門答案

我認為不可能(因為抽像類)沒有修改你的代碼。

我有一個類似的問題,最終創建一個私有的程序集的新對象,我有我的存儲庫派生自抽象基類。

此類不是抽象的,只對存儲數據的存儲庫類可見,此類具有實際表所需的所有方法。



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