实体框架 - 连接新添加的Poco实体并加载子对象(插入/添加)

时间:2013-06-29 00:25:35

标签: entity-framework orm

我想知道是否可以连接添加到DbContext的新创建的(poco)实体(以便在导航时延迟加载子对象)

var user = new User();
user.LocationID = 3;
dbContext.Users.Add(user);
var locationName = user.Location.Name;

(注意:我知道我可以获取Location对象并直接分配它,上面的例子只是为了这个问题的目的)

(注意II:我可以创建一个代理对象,然后复制这些值,这样的对象将被连接(并进行延迟加载),但任何复杂的子对象(其他pocos)都不会包含在副本中)

有没有办法连接(或加载)添加的poco?

1 个答案:

答案 0 :(得分:4)

简短的回答是,在使用外键和POCO时,您可以在设置FK之后显式延迟加载引用属性,如下所示:

context.Entry(e).Reference(propName).Load();

如果您需要经常遍历对象图,那么值得考虑的是,在概念级别而不是外键属性上工作对您来说更容易。

当上下文跟踪由导航属性表示的实体时,可以在DetectChanges()上同步FK和导航属性。 documentation表示只有在对象具有永久密钥时才会出现这种情况。

  

如果引用处于添加状态(在此示例中为课程   对象),引用导航属性将不会同步   使用新对象的键值,直到调用SaveChanges。   不会发生同步,因为对象上下文不会   包含添加对象的永久键,直到它们被保存。

但是,当处理Added状态且没有永久密钥的新添加实体的属性时,文档似乎不正确或具有误导性,并且仍然会发生导航属性和外键的同步。 / p>

以下是我自己的数据模型上的一些测试代码,我用它来研究这个问题。这是使用EF5和.Net4,据我所知,实际上是EF4.3。

using (MyContext context = new MyContext())
{
  /*
   * Uncomment these lines to test assigning FK Id when entity is being tracked
   */
  Customer cust1 = context.Customers.OrderBy(x => x.Id).First();
  Customer cust2 = context.Customers.OrderBy(x => x.Id).Skip(1).First();

  /*
   * Uncomment these lines to test assigning FK Id 
   * without having entity loaded in ObjectStateManager
   */
  //Customer cust1 = context.Customers.AsNoTracking().OrderBy(x => x.Id).First();
  //Customer cust2 = context.Customers.AsNoTracking()
  //                         .OrderBy(x => x.Id).Skip(1).First();

  //new entities
  Quote proxyQ = context.Quotes.Create();
  Quote pocoQ = new Quote();

  /*
   * if adding the new entities to context before setting FK properties
   * DetectChanges must be called later to attempt sync with nav props
   */
  context.Quotes.Add(proxyQ);
  context.Quotes.Add(pocoQ);

  //set FK Customer ids
  proxyQ.CustomerId = cust1.Id;
  pocoQ.CustomerId = cust2.Id;

  /*
   * FK / nav prop sync happens on DetectChanges() if the Customer 
   * entity is being tracked
   * it must be explicitly called if it has not been called using 
   * one of the AutoDetectChanges functions in order to sync
   */
  context.ChangeTracker.DetectChanges();

  /*
   * Alternatively, if the new entities are added to context after setting FK props
   * and AutoDetectChanges is enabled then DetectChanges is called implicitly and
   * FK / nav prop sync will happen here if the matching Customer entity is 
   * being tracked by the context.
   */
  //context.Quotes.Add(proxyQ); 
  //context.Quotes.Add(pocoQ);

  /*
   * If assigning FK Id and the entity the id represents is not tracked then 
   * proxy will lazy load Customer here.
   */
  Console.WriteLine("Proxy quote with key {0} linked to customer with name {1}",
   proxyQ.Id.ToString(), proxyQ.Customer != null ? proxyQ.Customer.Name : "null");

  /*
   * Obviously no lazy loading of Customer can occur here for a POCO
   */
  Console.WriteLine("POCO quote with key {0} linked to customer with name {1}",
   pocoQ.Id.ToString(), pocoQ.Customer != null ? pocoQ.Customer.Name : "null");

  /*
   * But we can explicit lazy load when using POCO if we have assigned 
   * an FK Customer Id to a POCO quote and the Customer entity is not 
   * being tracked by context
   */
   //context.Entry(pocoQ).Reference("Customer").Load();
   //Console.WriteLine("POCO quote with key {0} linked to customer with name {1}",
   //  pocoQ.Id.ToString(), pocoQ.Customer != null ? pocoQ.Customer.Name : "null");