我试图用一些精巧的查询替换讨厌的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?
我们选择“既不设置它”
我认为不可能(因为抽象类)没有修改你的代码。
我有一个类似的问题,最终创建一个私有的程序集的新对象,我有我的存储库派生自抽象基类。
此类不是抽象的,只对存储数据的存储库类可见,此类具有实际表所需的所有方法。