实体框架在插入时应立即包含属性

时间:2014-05-07 12:07:13

标签: c# entity-framework

我有一些看起来像这样的代码:

var query = from row in context.Orders.Include("Customer") 
where row.Id = 5 
select row;

var result = query.FirstOrDefault();

if(result == null)
{
    result = new Order {CustomerId=5,...}
    context.Orders.Add(result);
    context.SaveChanges();

    // at this point result.Customer is null
    // and is not lazy-loaded by EF on access
}

return result;

正如您在上面的代码中看到的那样,如果插入发生,则结果的Customer属性不包括在内,稍后在我的代码中给我一个错误。

如何在插入result.Customer时确保从数据库加载result?我可以不手动选择吗?

1 个答案:

答案 0 :(得分:3)

如果不选择它,EF就无法激活客户对象。你在这里只是一个Id。 Something 需要转到数据库并找到Id#5的客户对象。

EF不能在此处延迟加载,因为您的result实际上是POCO Order,而不是知道如何延迟加载的EF生成的代理。

最简单的方法可能是查询客户并按ID设置关系,而不是(或同样)设置ID: -

if(result == null)
{
  result = new Order
  {
    Customer = context.Customers.Single(x => x.Id == 5);
    ...
  };
  context.Orders.Add(result);
  context.SaveChanges();
}

或者,您可以使用context.Orders.Create(),这样您就可以首先使用EF代理: -

if(result == null)
{
  var result = context.Orders.Create();
  result.CustomerId = 5;
  ...
}

请注意,根据您域中预期的行为,将查询和命令混合起来往往不是一个好主意。您可能想要围绕CQRS进行一些阅读 - 例如http://cqrs.nu/

创建订单是一项非常重要的操作。将它楔入一个查询,查找尚不存在的订单可能会回来并在将来咬你。