10

我使用 LINQ-to-SQL 从具有一对多关系的两个表的数据库中加载数据(一个配方有许多成分)。

我加载一个配方,LINQ 将成分对象检索到一个绑定到列表框的实体集中。

如果我想从食谱中删除一些成分,我会收到“尝试删除食谱和成分之间的关​​系。但是,关系的一个外键 (Ingredient.RecipeID) 不能设置为空。

我通过将“DeleteOnNull="true"' 添加到 DBML 文件中,使用众所周知的解决方案解决了这个问题。但添加此设置仅在我们删除从数据库中检索到的成分对象时才消除问题。

问题在于在代码中创建的成分对象(添加到配方中)并添加到成分的 EntitySet 集合中,然后在调用 SubmitUpdates 之前删除。然后,同样的异常再次发生。这通常发生在一个新的、未保存的食谱上,当用户向其中添加成分时,犯了一个错误并从食谱中删除了一种成分。我将 DeleteOnNull 添加到 DBML 中的两个 'Association Name="Recipe_Ingredient"' 行。

我应该如何删除这些对象?我目前看到的唯一解决方案是,我会将成分加载到不在 DataContext 下的集合中,然后在保存时,从配方中删除所有成分,然后从该缓存中再次添加。

4

7 回答 7

8
        try
        {
            // Needed for existing records, but will fail for new records
            yourLINQDataContext.Ingredients.DeleteOnSubmit(ingredient);
        }
        catch (Exception)
        {
            // Swallow
        }

        yourRecipeObject.Ingredients.Remove(ingredient);
于 2008-12-23T05:21:23.197 回答
3

几天前,当我问“如何为带有确定/取消按钮的数据绑定 WPF 对话框设计支持数据类型? ”时,您似乎正在寻找我自己正在寻找的东西。

答案是来自 Paul Stovell 的一篇有趣的文章,描述了一个用于 Linq to Sql的示例 IEditable 适配器。这将让您以通用方式创建所需的“应用/取消”语义,而无需通过完整的自定义编写层将自己与底层 ORm 生成的类完全分离。

总的来说,这是一个非常巧妙的技巧,它基本上可以让你回避你现在正在解决的问题。:)

另一方面,我很好奇为什么你的配方与成分的关系是 1:n 而不是 m:n。是为了简单吗?我在很多食谱中都使用大蒜。:)

于 2008-12-23T05:51:50.297 回答
2
// Create new entities
Cart c = new Cart();
CartEntry ce = new CartEntry();
ce.Cart = c;

// Delete the entry
c.CartEntries.Remove(ce);
dc.Cartentries.Attach(ce);
dc.CartEntries.DeleteOnSubmit(ce);

// Insert the cart into database
dc.Carts.InsertOnSubmit(c);
dc.SubmitChanges();

问题解释:实体 c 和 ce 都与数据上下文无关 - 它们没有被跟踪。EntitySet.Remove()(第一个删除行)只删除 c 和 ce 之间的关系。虽然 c 可以在没有关联的购物车条目的情况下存在,但由于外键约束,ce 不能在没有关联的购物车的情况下存在。在向数据库提交更改时,断开连接的 ce 也会被处理,从而导致约束违反和异常。

为了摆脱未跟踪和断开连接的购物车条目,您需要将其附加到您的数据上下文(使其被跟踪),然后将其标记为在提交时删除。您提交更改的那一刻,购物车条目将被正确删除,不会导致异常。

有关该问题的更多详细信息,请查看:http: //msdn.microsoft.com/en-us/library/bb546187%28v=VS.100%29.aspx

于 2010-05-31T10:34:05.570 回答
0

我遇到了类似的问题,作为一种解决方法,我需要调用 DataContext.GetChanges(),然后一切似乎又开始流行了 :)

另一个问题可能是您绑定到列而不是实体属性,因此引用集合没有更新(已经由其他人声明,但强制执行该事实)。

于 2009-03-09T11:29:14.500 回答
0

我有完全相同的问题。我有一个父/子层次结构,当添加和删除子实体而不保存到数据库时,我收到“尝试删除关系”异常。

我发现只有在保存之前将子对象的对象样式属性设置为另一个 linq-sql 实体时才会出现此问题。例如

1.这会产生错误

 RetailAccountCustomerCard racc = new RetailAccountCustomerCard();

 Card addedCard = _idc.Cards.Where(c => c.CardId == card.CardId).ToList().First();

 racc.Card = addedCard;

 this.CurrentCustomer.RetailAccountCardsBindingList.Add(racc); 

 // Some code triggered by the user before saving to the db

 CurrentCustomer.RetailAccountCardsBindingList.Remove(racc);

2.这不会产生错误

 RetailAccountCustomerCard racc = new RetailAccountCustomerCard();

 racc.CardId = card.CardId;  // note that I have set the Id property not the object

 this.CurrentCustomer.RetailAccountCardsBindingList.Add(racc); 


 // Some code triggered by the user before saving to the db

 CurrentCustomer.RetailAccountCardsBindingList.Remove(racc);

奇怪的是,1. 中出现的错误指定问题与关系有关,它位于 RetailAccountCustomerCard 的 RetailAccountCustomerId 属性上。与我添加的 Card 对象无关。似乎简单地设置新实体的任何对象属性都会触发问题。

注意。示例 1 在保存方面工作正常,只有在保存之前删除新实体时才会导致问题。

于 2009-01-20T00:42:29.580 回答
0

您需要将保存代码与 GUI 中的事件分离,似乎您有点急于在尘埃落定之前将东西保存到数据库中,并且您正在排队并从数据库中删除从未到达那里的东西首先,如果您能确定用户“提交”他们的更改的时间点,并在那个时候处理 GUI 的全部条件,那将是最好的——这将为您节省一堆意大利面条式代码。

我也很想知道您的实体是否具有自动编号 ID,或者您是否正在使用其他一些 ID 机制。您可能正在向数据库发送 DELETE 以获取尚未提交的成分记录,如果这些记录包含 NULL ID,我认为 linq 可能会变得讨厌。

您是否将文本编写器连接到 DataContext.Log 以查看在您获得异常之前生成了哪些类型的 SQL?

于 2008-12-23T02:44:47.990 回答
0

谢谢你的回答,我会检查帖子,看看我能做什么。我必须说我很惊讶甚至看到这个问题发生,对我来说似乎很自然可以将记录添加到 LINQ 提供的数据“缓存”,然后决定删除其中一些然后提交。更改跟踪应该能够处理这个问题。我刚从 LINQ 开始,所以我可能在代码的某个地方犯了一个愚蠢的错误(不会是第一个)。

另一方面:你说得对,大蒜可以属于许多食谱(不是我的鸡尾酒食谱想的!)。我实际上是用文章对象/表来建模的。但是对于食谱,您需要数量。因此,在我的模型中,您有一个包含 1:n 成分的食谱,每个成分都有一个数量、一个 1:1 链接到一篇文章(它有一个名称、一个酒精含量和一些数据来建立一个可互换的层次结构)和一个1:1 链接到一个单位(使数量有意义)。所以从某种意义上说,成分表在食谱和文章之间建立了 M:N 关系,同时为每个单独的链接对添加了一些额外的信息。

于 2008-12-23T07:04:40.150 回答