每次我开始研究一个新项目时,我都会和自己进行一场心理辩论,而我正在设计我的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,并且使用了独立的关联,它不仅感觉更多OO,而且(延迟加载)的优势在于可以让我访问整个Customer对象,而不仅仅是ID。例如,这允许我检索Order实例,然后执行Order.Customer.FirstName
而无需明确地进行连接,这非常方便。
回顾一下,我的问题是:
答案 0 :(得分:106)
如果您想充分利用ORM,您肯定会使用实体参考:
public class Order
{
public int ID { get; set; }
public Customer Customer { get; set; } // <-- Customer object
...
}
从具有FK的数据库生成实体模型后,它将始终生成实体引用。如果您不想使用它们,则必须手动修改EDMX文件并添加表示FK的属性。至少在实体框架v1中就是这种情况,其中只允许独立关联。
实体框架v4提供了一种称为外键关联的新型关联。独立和外键关联之间最明显的区别在于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
!外键关联
ObjectStateManager
中表示为单独的对象。因此,您必须遵守一些特殊规则。如果要使用外键关联,则必须在实体数据模型向导中勾选在模型中包含外键列。
编辑:
我发现这两种类型的关联之间的区别并不是很清楚,所以I wrote a short article用更多细节和我自己对此的看法来涵盖这一点。
答案 1 :(得分:33)
同时使用。并使您的实体引用虚拟以允许延迟加载。像这样:
public class Order
{
public int ID { get; set; }
public int CustomerID { get; set; }
public virtual Customer Customer { get; set; } // <-- Customer object
...
}
这节省了不必要的数据库查找,允许延迟加载,并允许您在知道自己想要的内容时轻松查看/设置ID。请注意,两者都不会以任何方式更改表结构。
答案 2 :(得分:8)
独立关联与AddOrUpdate
方法中常用的Seed
无效。当引用是现有项时,它将被重新插入。
// 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);
我们有预期的行为,现有客户将与新订单相关联。
答案 3 :(得分:4)
我赞成使用对象方法来避免不必要的查找。当您调用工厂方法来构建整个实体时(使用嵌套实体的简单回调代码),可以很容易地填充属性对象。除了内存使用外,我没有看到任何缺点(但是你可以正确地缓存你的对象吗?)。因此,您所做的就是将堆栈替换为堆,并通过不执行查找来获得性能提升。我希望这是有道理的。