代码优先:独立协会与外键协会?

每当我开始一个新项目的工作,我正在devise我的POCO时,我都会与自己进行心理辩论。 我见过很多教程/代码示例似乎赞成外键协会

外键关联

public class Order { public int ID { get; set; } public int CustomerID { get; set; } // <-- Customer ID ... } 

独立协会相反:

独立协会

 public class Order { public int ID { get; set; } public Customer Customer { get; set; } // <-- Customer object ... } 

我曾经使用NHibernate,并使用独立的关联,不仅感到更多的面向对象,而且(与延迟加载)有优势,让我访问整个客户对象,而不是只是其ID。 这允许我,例如,检索一个Order实例,然后做Order.Customer.FirstName而不必明确做一个连接,这是非常方便的。

所以回顾一下,我的问题是:

  1. 使用独立协会有什么重大的缺点? 和…
  2. 如果没有,那么使用外键协会的理由是什么呢?

如果你想充分利用ORM,你一定会使用实体引用:

 public class Order { public int ID { get; set; } public Customer Customer { get; set; } // <-- Customer object ... } 

一旦用FK从数据库生成实体模型,它将始终生成实体引用。 如果您不想使用它们,您必须手动修改EDMX文件并添加表示FK的属性。 entity frameworkv1中至less有这种情况,只有独立协会被允许。

entity frameworkv4提供了一种称为外键关联的新型关联。 独立与外键关联最明显的区别在Order类中:

 public class Order { public int ID { get; set; } public int CustomerId { get; set; } // <-- Customer ID public Customer Customer { get; set; } // <-- Customer object ... } 

正如你所看到的,你有FK属性和实体引用。 两种关联之间有更多的差异:

独立协会

  • 它在ObjectStateManager表示为单独的对象。 它有它自己的EntityState
  • build立联系时,您总是需要联系两端的实体
  • 该关联以与实体相同的方式映射。

外键关联

  • 它在ObjectStateManager不表示为单独的对象。 由于你必须遵循一些特殊的规则。
  • 在build立关联时,你不需要关联的两端。 拥有子实体和父实体的PK就足够了,但PK值必须是唯一的。 因此,在使用外键关联时,还必须将临时唯一标识分配给关系中使用的新生成的实体。
  • 这个关联没有被映射,而是定义了参照约束。

如果您想使用外键关联,则必须在实体数据模型向导中勾选包含模型外键列

编辑:

我发现这两种关联之间的区别不是很清楚,所以我写了一篇关于这个的简短文章 ,里面有更多的细节和我自己的看法。

同时使用。 并使您的实体引用虚拟允许延迟加载。 喜欢这个:

 public class Order { public int ID { get; set; } public int CustomerID { get; set; } public virtual Customer Customer { get; set; } // <-- Customer object ... } 

这节省了不必要的数据库查找,允许延迟加载,并允许您轻松查看/设置ID,如果你知道你想要的是什么。 请注意,两者都不会以任何方式更改您的表结构。

独立的关联与通常在Seed方法中使用的AddOrUpdateAddOrUpdate 。 当引用是一个现有的项目时,它将被重新插入。

 // Existing customer. var customer = new Customer { Id = 1, Name = "edit name" }; db.Set<Customer>().AddOrUpdate(customer); // New order. var order = new Order { Id = 1, Customer = customer }; db.Set<Order>().AddOrUpdate(order); 

结果是现有客户将被重新插入,并且新(重新插入)的客户将与新订单相关联。


除非我们使用外键关联并分配id。

  // Existing customer. var customer = new Customer { Id = 1, Name = "edit name" }; db.Set<Customer>().AddOrUpdate(customer); // New order. var order = new Order { Id = 1, CustomerId = customer.Id }; db.Set<Order>().AddOrUpdate(order); 

我们有预期的行为,现有的客户将与新订单相关联。

我赞成使用对象方法来避免不必要的查找。 当您调用工厂方法来构build整个实体(使用嵌套实体的简单callback代码)时,属性对象可以很容易地填充。 除了内存使用情况(但是你会caching对象的权利?),我没有什么缺点可以看到。 所以,你所做的只是把堆栈换成堆栈,并从不执行查找来获得性能提升。 我希望这是有道理的。