C# 使用LINQ to SQL创建查找时ForeignKeyReferenceAlreadyHasValueException

C# 使用LINQ to SQL创建查找时ForeignKeyReferenceAlreadyHasValueException,c#,.net,linq-to-sql,C#,.net,Linq To Sql,我刚接触C#和.NET,刚开始学习LINQ to SQL,我喜欢它。但是我觉得这是一件很烦人的事。由于“ForeignKeyReferenceAlreadyHasValueException”,实现查找非常复杂!没有简单直接的方法可以做到这一点!我注意到,如果我删除LINQ实体之间的所有关联,“ForeignKeyReferenceAlreadyHasValueException”问题就不再存在了!我计划开发小型WinForms数据库应用程序,不超过100个表 所以我的问题是: 如果我使用LIN

我刚接触C#和.NET,刚开始学习LINQ to SQL,我喜欢它。但是我觉得这是一件很烦人的事。由于“ForeignKeyReferenceAlreadyHasValueException”,实现查找非常复杂!没有简单直接的方法可以做到这一点!我注意到,如果我删除LINQ实体之间的所有关联,“ForeignKeyReferenceAlreadyHasValueException”问题就不再存在了!我计划开发小型WinForms数据库应用程序,不超过100个表

所以我的问题是:


如果我使用LINQ2SQL,但删除LINQ实体之间的所有关联并将关系保留在数据库中,那么会有什么损失/风险

当然,你失去的是人际关系。通常,LINQ to SQL将自动填充抽象关系的有用集合,例如:

var query = db.Orders.Where(o => o.Products.Count() > n);
                                   ^^^^^^^^
                           // You would lose this
然后你就必须用更迂回的方式来写,例如

var query = db.Orders.Where(o =>
                db.OrderProducts.Count(p => p.ProductId == o.ProductId) > n);

基本上,您将失去查询支持、延迟加载、IntelliSense等。例如,如果删除用户问题之间的关联,您将不会有类似的情况:

from u in context.Users
where u.Questions.Count > 2
select u;
LINQ的要点是为您提供在C#代码中实现关系数据库模型所需的所有构造,使您能够查询该模型。如果删除所有的关联/关系,LINQ to SQL将失去其用途

关于你得到的:

如果关联属性为 指定了一个值,您无法更改 外键字段不再存在,您必须 通过改变来改变关系 关联属性。对于 例如,使用Customer和Order from Northwind样本数据库。如果 订单上的“客户”属性为 指定了一个不能再使用的值 手动更改订单的CustomerID 字段,因为它必须与 顾客。但是你可以,, 更改“客户”属性 直接分配给它一个新客户 例如。这一行动将 自动更新CustomerID 要匹配的字段作者Matt Warren(LINQ to SQL架构师)

这就是你需要做的来解决你的问题:

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

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

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 

您正在以错误的方式进行这些关系更改。如果您有一个订单对象,并将一个客户对象作为成员附加到该订单对象,则可以如下方式查看客户信息:

var order = db.Orders.Single(x => x.ID == 40);
var cusName = order.Customer.GetFullCustomerName();
但是,如果需要在数据库中为该订单更改该客户,则不能仅将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();

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

您能否发布一个使用
ToLookup
的查询,并引发您提到的异常?还要提到在该查询中使用的哪些表/列是通过外键关系关联的。当我写“lookups”时,我指的是LookUpEdit或ComboBox在某个GridView中作为独立编辑器或就地编辑器。(示例:设置DataSource、DisplayMember和ValueMember属性可用于DataSet,但使用LINQ2SQL设置ForeignKeyReferenceAlreadyHasValueException)我明白您的观点。。。但是当使用像LookUpEdit这样的控件时,如何解决这个“ForeignKeyReferenceAlreadyHasValueException”(请阅读上面的注释)!?由于LINQ2SQL易于使用且不受限制,不能简单地绑定LookUpEdit-s,而且总是要做一些即兴创作,这只会让这种轻松感消失!请您详细说明最后一条评论,并给我举个例子(比如客户位置)以及如何绑定LookUpEdit(DataSource、DisplayMember、ValueMember!?)查看我提供给您的最后一个链接。这实际上是评论试图告诉你的。。。你必须分配整个实体/对象,而不仅仅是Id属性。在我问这个问题之前,我已经分配了。。。我的问题是关于绑定LookUpEdit控件的更多信息。。。我想我还是不明白。