我遇到ObjectContext.LoadProperty
(EF 4数据库优先)的困难(字符串和表达式重载对我来说都表现出相同的行为)。给出以下简单模式:
Product
--------------
ProductId (pk)
...
Order
--------------
OrderId (pk)
...
OrderItem
--------------
OrderId (pk, fk Order),
ItemNumber (pk),
ProductId (fk Product)
...
因为我发现它在我的特定场景中的性能优于Includes
,所以我使用LoadProperty
来填充相关实体。例如,
Order ord = context.Orders.Where(o => o.OrderId = 1).FirstOrDefault();
context.LoadProperty(ord, o => o.Items); // Items is the navigation property name for the
OrderItem -> Order relationship
foreach(var i in ord.Items)
{
context.LoadProperty(i, oi => oi.Product);
}
这已经存在了一段时间并且已经有效(正如您所期望的那样)就好了。但是,今天早上我们开始遇到一种情况,即使在调用LoadProperty
之后,i.Product
仍然为空。 i.ProductId
有效,我甚至可以明确地加载产品:
var product = context.Products.Where(p => p.ProductId == i.ProductId).FirstOrDefault();
但LoadProperty
不会加载该对象。抛出没有异常,它只是不加载它。我也试过指定MergeOptions.OverwriteChanges
(即使没有),结果可以预测相同。
什么可能导致ObjectContext.LoadProperty
以这种方式无声地失败?
答案 0 :(得分:0)
我发现这似乎是一个问题(如果不是一个彻头彻尾的错误)与EF的LoadProperty
功能的工作方式。
OrderItem
和Product
表的ProductId
值因大小写,尾随空格或两者而异。鉴于SQL Server的默认排序规则,这是合法的,并且保持了参照完整性。这就是为什么对产品的查询有效的原因,但似乎EF在某处内部进行了关键比较,并对这些值进行了更严格的判断。
如果您自己遇到此问题,可以在查询中使用T-SQL DATALENGTH
函数检查尾随空格,并且可以使用不同的排序规则来比较大小写。
例如,您可以使用以下内容查看上述模型中的差异:
select
*
from OrderItem oi
join Product p on p.ProductId = oi.ProductId -- default collation; case and
-- trailing spaces ignored
where DATALENGTH(oi.ProductId) <> DATALENGTH(p.Product) -- trailing spaces differ
or oi.ProductId <> p.ProductId COLLATE SQL_Latin1_General_CP1_CS_AS -- case differs
请注意,可以仅使用排序规则来比较尾随空格和字符大小写;如果有人知道这样做的排序规则的名称,请随时编辑此答案或发表评论,我会更新。在那之前,这应该做必要的事情。