从抽象类引用继承的 EntitySet 的 dapper PropInfo Setter 为 null
我正在尝试用一些简洁的查询替换令人讨厌的 LINQ 2 SQL 命中,以提高性能。为此,我必须将一堆不同的对象编织在一起,以创建保存 ASN 信息所需的所有信息所需的大对象。
我当前遇到的问题是抽象类 Orders,该类由两个单独的类 AutionOrder 和 MerchantOrder 使用鉴别器属性实现。
由于我无法使用 dapper 创建一个抽象类的对象,所以我改为使用公共类之一。然而,当它构建对象时,它在 GetSettableProps
内部失败,它正在寻找正确的 DeclaringType
,但 GetProperty
方法在它时返回 null正在查找内部
属性或者EntitySet
属性。我尝试使用 t.BaseType.GetProperty 以及 p.GetAccessors().First().GetBaseDefinition().DeclaringType.GetProperty(p.Name) 来破解它。 GetSetMethod(true) 没有成功。
虚拟对象:
订单
<块引用>订单ID、名称、地址、行版本(内部)、发货(EntitySet)、订单详细信息(EntitySet)、客户(EntityRef)
发货
<块引用>货件 ID、订单 ID、追踪号码
订单详情
<块引用>订单详细信息 ID、订单 ID、产品、数量、价格
客户
<块引用>客户 ID、姓名
对于这个特定的 SQL 命中,我试图获取一些我需要的 1 对 1 关系映射。
从订单中选择 o.* as o left join Customers as c on o.CustomerID = c.CustomerID where o.OrderID in (1,2,3);
这就是我用来利用 dapper 并让它发挥魔力的方法:
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 时失败 - 将其切换为公共而不是内部解决了这个问题 - 尽管不是所希望的。但当它尝试为订单创建 Shipments 对象时,它会失败。同样,当 Order 是公共类时,这一切都不是问题。
此外,我还进行单独的查询以引入多对一关系,例如发货到订单和订单详细信息到订单,并将结果规范化为正确的订单对象。 MerchantOrder 几乎是一个空类,没有真正的特殊逻辑。这里的区别在于我们最终如何找到在实际 SQL 命中之前抽象出来的 CustomerID。
我还使用截至 2011 年 12 月 20 日的最新版本 dapper。
我真的很喜欢 dapper,但这个问题让我头晕目眩 - 所以感谢您的帮助!
I am trying to replace a nasty LINQ 2 SQL hit with some dapper queries to improve performanace. In doing so I have to weave a bunch of different objects together in order to create the big object required to hold all the information I need for ASN information.
The current problem I am having is with an abstract class Orders, this class is implemented by two seperate classes AutionOrder and MerchantOrder using a discriminator property.
Since I cannot use dapper to create a object that is an abstract class I am instead using one of the public classes. however when it goes to build the object it is failing inside of GetSettableProps
it is finding the proper DeclaringType
but the GetProperty
method is returning null when it is looking for an property that is internal
or is an EntitySet
. I've tried to hack around it using t.BaseType.GetProperty
as well as p.GetAccessors().First().GetBaseDefinition().DeclaringType.GetProperty(p.Name).GetSetMethod(true)
with no success.
dummy objects:
Order
OrderID, Name, Address, RowVersion(internal), Shipments(EntitySet),OrderDetails(EntitySet), Customer(EntityRef)
Shipment
ShipmentID, OrderID, TrackingNumber
OrderDetails
OrderDetailID, OrderID, Product, QTY, Price
Customer
CustomerID, Name,
For this particular SQL hit I am trying to grab some of the 1 to 1 relationship mappings I need.
SELECT o.* from Orders as o left join Customers as c on o.CustomerID = c.CustomerID where o.OrderID in (1,2,3);
This is what I am using to utilize dapper and let it do it's magic:
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");
}
If I change Order to be a public class this problem goes away though, but this is not a desired side-effect. It is failing when trying to set the propInfo for RowVersion - switching this to public instead of internal solved this problem - although not desired. But then it fails when it is trying to create the Shipments objects for Order. Again none of this is an issue when Order is a public class.
Also I am doing separate queries to pull in Many to one relationships such as Shipments to Orders and OrderDetails to Orders and normalizing the results into a proper Order Object.
MerchantOrder is pretty much an empty class with no real special logic. The discriminating different here is just how we end up finding the CustomerID which is abstracted away prior to the actual SQL hit anyway.
Also I am using the latest version of dapper as of 12/20/2011.
I really like dapper, but this problem is making my head asplode - so thanks for the help!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是一个错误,现已在主干中修复:
一个旁注是,根据设计,我们不会在基类中设置私有字段或属性。这种行为可能很神奇并且不一致。
例如:
我们选择“都不设置”
This was a bug, that is now fixed in trunk:
One side note is that, by design, we do not set private fields or properties in the base classes. The behaviour can be magical and not consistent.
Eg:
We went with "set it on neither"
我认为不修改代码是不可能的(因为抽象类)。
我遇到了类似的问题,最终创建了一个程序集私有的新对象,其中我有从抽象基类派生的存储库。
这个类不是抽象的,仅对存储数据的存储库类可见,该类具有实际表所需的所有方法。
I think is not possible (because of the abstract class) without modifying your code.
I had a similar problem and ended up creating a new object private to the assembly where I have my repositories that derived from the abstract base class.
This class is not abstract and only visible to the repository class that stores the data, this class had all the required methods for the actual table.