使用LINQ to SQL创建Lookup时,ForeignKeyReferenceAlreadyHasValueException

Emi*_*irZ 5 .net c# linq-to-sql

我是C#和.NET的新手,我刚开始学习LINQ to SQL,我喜欢它.但是......我发现这个非常烦人的事情.由于"ForeignKeyReferenceAlreadyHasValueException",实现lookUps非常复杂!没有简单的直接方式!我注意到,如果删除LINQ实体之间的所有关联,"ForeignKeyReferenceAlreadyHasValueException"问题就不复存在!我计划开发小型WinForms数据库应用程序,不超过100个表...

所以我的问题是:

如果我使用LINQ2SQL但删除LINQ实体之间的所有关联并在数据库中保持关系,我会失去/冒这个风险?

Len*_*rri 5

基本上你将失去查询支持,延迟加载,智能感知等.例如,如果你删除用户问题之间的关联,你将不会有这样的事情:

from u in context.Users
where u.Questions.Count > 2
select u;
Run Code Online (Sandbox Code Playgroud)

LINQ的目的是为您提供在C#代码中实现关系数据库模型所需的所有构造,使您能够查询该模型.如果删除所有关联/关系LINQ to SQL就失去了它的目的.

关于你得到的例外情况:

如果为关联属性分配了值,则无法再更改外键字段,则必须通过更改关联属性来更改关系.例如,使用Northwind示例数据库中的Customer和Order.如果为订单上的"客户"属性分配了值,则您无法再手动更改订单的CustomerID字段,因为它必须与客户的PK匹配.但是,您可以直接更改"客户"属性,为其分配新的客户实例.此操作将自动更新CustomerID字段以进行匹配.作者:Matt Warren(LINQ to SQL架构师)

这是您解决问题所需要做的事情:

LINQ to SQL ForeignKeyReferenceAlreadyHasValueException错误

对于LookUps和LINQ,请执行以下操作:

LINQ,Lookups,ForeignKeyReferenceAlreadyHasValueException

例如,在绑定组合框时使用此代码:

With cboCategory 
.DataSource = From Category In db.Categories Order By Category.Name
              Select Category 
.DisplayMember = "Name" 
.ValueMember = "ID"    don't set value member: http://tinyurl.com/d9etoy 
.DataBindings.Add(New Binding("SelectedItem", ItemBindingSource, "Category")) 
End With 
Run Code Online (Sandbox Code Playgroud)


Gra*_*ham 5

您正在以错误的方式进行这些关系更改.如果您有一个Order对象,其Customer对象作为成员附加到它,您可以查看客户信息,如下所示:

var order = db.Orders.Single(x => x.ID == 40);
var cusName = order.Customer.GetFullCustomerName();
Run Code Online (Sandbox Code Playgroud)

但是,如果您需要在数据库中更改该订单的客户,则不能将Order.CustomerID字段设置为新ID.这将抛出ForeignKeyReferenceAlreadyHasValueException错误.

// wrong way...
order.CustomerID = 45; // id of the new customer
// BOOOOM goes the error here.

// right way...
order.Customer = db.Customer.Single(x => x.ID == 45);

db.SubmitChanges();
Run Code Online (Sandbox Code Playgroud)

换句话说,一旦从数据库中下载Order.Customer,就不能通过更改Orders表中该行上的外键来手动更改关联的客户.您必须将order.Customer成员设置为另一个实时Customer对象,然后将更改以此方式回滚到数据库.