在使用Entity Framework时,当设置外键时,我应该设置导航属性还是外键属性?

6

我有一些类似这样的代码:

var customer = dbcontext.Customers.Find(1);

var order = new Order();
order.CustomerId = customer.Id;

dbcontext.Orders.Add(order);
dbcontext.SaveChanges();

在设置导航属性时,是最佳实践是这样做还是通过设置关系来进行设置?

var customer = dbcontext.Customers.Find(1);

var order = new Order();
order.Customer = customer; //Set navigation prop as opposed to FK field

dbcontext.Orders.Add(order);    
dbcontext.SaveChanges();

哪种方法被认为是最佳实践或首选方法?

3个回答

2
我的建议是,实体应该公开导航属性外键,但绝不两者都有。如果使用导航属性,请使用影子属性(EF Core)代替FK。
原因在于更新和确保实体始终处于完整状态。当两者都存在时,EF直到调用SaveChanges()才同步它们。如果在更新和SaveChanges()之间调用了期望其中之一的代码,则可能会导致错误(例如验证调用等)。即您设置了FK,但是某些代码检查了Nav属性。
在大多数情况下,我更喜欢导航属性,但对于我真正不需要加载的引用(超出满足数据完整性的范围),如常量/枚举键,或者在我想要最大性能的情况下进行批量更新操作等情况下,我会使用FK。

2

您是否担心性能问题?

A) 不担心:如果您没有担心,那么您应该始终使用导航属性以获得可读性。

B) 担心:那么您应该在一开始就使用.Select(c => c.id)查询客户,并仍然只使用导航属性。在这种情况下,很明显您不会更新Customer的任何其他字段,因为您只是将其与设置FK进行比较。

var customer = dbcontext.Customers
                        .Find(1)
                        .Select(b => new Customer { Id = b.Id } );

var order = new Order();
order.Customer = customer; //Set navigation prop as opposed to FK field

dbcontext.Orders.Add(order);    
dbcontext.SaveChanges();

C)非常是:在您提供的这个简化的示例中,查询具有其PK的Customer,然后仅使用PK是毫无意义的。您已经拥有所需的所有信息,可以直接在Order中设置它。但是,我们将不得不手动附加它,否则 efcore 将尝试创建一个已存在的 Customer

var order = new Order();
order.Customer = new Customer { Id = 1 };
dbcontext.Attach<Customer>(order.Customer); 

dbcontext.Orders.Add(order);    
dbcontext.SaveChanges();

1
如果您的代码需要客户对象进行进一步操作,两种方法都可以,EF代理会处理所有事情。
否则,通过设置FK,您可以避免查询Customers dbset以检索客户信息,提高操作效率(您已经有了客户ID)。我通常更喜欢这种方式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接