我从外部源加载数据作为 xml,它被反序列化,然后我循环对象以将它们汇集到我的域实体中。
为了创建数据之间的关系并减少数据库调用,我编写了一个扩展方法来尝试从 DbSet.Local 中检索项目,如果它没有找到项目,那么它使用 DbSet.SingleOrDefault() 来查询数据库,如下所示.
public static TEntity SingleOrDefaultLocalFirst<TEntity>(this IDbSet<TEntity> set,
Func<TEntity, bool> predicate) where TEntity : class
{
if (set == null)
throw new ArgumentNullException("set");
if (predicate == null)
throw new ArgumentNullException("predicate");
TEntity results = null;
try
{
results = set.Local.SingleOrDefault(predicate);
}
catch (Exception e)
{
Debug.WriteLine(e.Message, "Error");
}
if (results != null)
{
return results;
}
return set.SingleOrDefault(predicate);
}
try catch 块用于抑制我试图解决的问题。
由于某种原因,查询本地商店时的导航属性未填充。所以如果我使用类似的东西
(x=>x.Participant.Event.ExternalId==newItem.Id)
作为我的 lambda,Participant nav 属性为空。
我觉得应该有某种方法可以让这段代码不会始终生成空引用错误。
在我的循环开始使用之前,我已经尝试从数据库中显式加载参与者和事件数据
context.Participant.Load()
但这没有什么区别。
有人可以告诉我为什么导航属性为空以及如何以最有效的方式填充它们吗?
而且,如果有人想知道我为什么不使用 Find(),那是因为外部数据是在许多属性上键入的,并且外部 id 字段不是我系统中的主键。
更新:
我不会花时间包含我的真实代码,因为有太多东西需要精简为一个可用的示例,所以我将尝试使用 Customer/Order/OrderItem 典型示例。
真正的问题是,当您有一个嵌套实体并尝试使用以下方法检查是否存在时:
var orderLine = context.OrderLineItems.Local.SingleOrDefault(x=>x.Order.Number == 1234)
即使在此使用之前将订单和客户显式加载到上下文中,它也会为订单抛出空引用错误
context.Orders.Load()
但是,如果你这样做:
var orderLine = context.OrderLineItems.SingleOrDefault(x=>x.Order.Number == 1234)
它会起作用的。
我想了解为什么调用 Local 时它不起作用。当相关的导航属性已经加载到上下文中时,为什么我们必须访问数据库来获取相关的导航属性?还是我错过了什么?