dapper PropInfo用于从抽象类引用继承的EntitySet的Setter为null

Joh*_*ohn 12 .net c# reflection abstract-class dapper

我试图用一些精巧的查询替换讨厌的LINQ 2 SQL命中以改善性能.在这样做时,我必须将一堆不同的对象编织在一起,以便创建保存ASN信息所需的所有信息所需的大对象.

我目前遇到的问题是抽象类Orders,这个类是由两个单独的类AutionOrder和MerchantOrder使用discriminator属性实现的.

由于我不能使用dapper来创建一个抽象类的对象,而是使用其中一个公共类.然而,当它构建对象时,它在其内部失败GetSettableProps是找到正确的DeclaringType但该GetProperty方法在寻找属于internal或是的属性时返回null EntitySet.我试图用它来破解它t.BaseType.GetProperty并且p.GetAccessors().First().GetBaseDefinition().DeclaringType.GetProperty(p.Name).GetSetMethod(true)没有成功.

虚拟对象:

订购

OrderID,名称,地址,RowVersion(内部),货件(EntitySet),OrderDetails(EntitySet),客户(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");
}
Run Code Online (Sandbox Code Playgroud)

如果我将Order改为公共类,这个问题就会消失,但这不是一个理想的副作用.尝试为RowVersion设置propInfo时失败 - 将此切换为公共而不是内部解决了这个问题 - 虽然不是所希望的.但是当它试图为Order创建Shipments对象时失败了.当Order是公共类时,这一点都不是问题.

此外,我正在进行单独的查询以引入多对一的关系,例如将订单发送到订单和订单的订单详细信息,并将结果规范化为正确的订单对象.MerchantOrder几乎是一个没有真正特殊逻辑的空类.这里区分不同的是我们最终找到在实际SQL命中之前被抽象出来的CustomerID.

此外,我在12/20/2011使用最新版本的dapper.

我真的很喜欢小巧玲珑,但这个问题让我头晕目眩 - 所以感谢你的帮助!

Sam*_*ron 7

这是一个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);

    }
Run Code Online (Sandbox Code Playgroud)

一方面注意,根据设计,我们不在基类中设置私有字段或属性.这种行为可能是神奇的,也不一致.

例如:

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?
Run Code Online (Sandbox Code Playgroud)

我们选择"既不设置它"