实体框架外键跟踪导致问题

本文关键字:问题 跟踪 框架 实体 | 更新日期: 2023-09-27 17:58:13

使用EF4,VS 2010中的模型优先方法:

考虑以下EntityModel:

"OrderBase"是一个抽象实体,只有一个属性"Name"

"Detail"(具有一个属性"Text")是一个与"OrderBase"有多对一关联的实体(即一个OrderBase有多个Details)

"Comment"(具有一个属性"Text")是一个与"OrderBase"有多对一关联的实体(即一个OrderBase有多个Comments)

"MusicOrder"是从"OrderBase"派生的实体,只有一个属性"Quantity"(int)

"SongOrder"是从"OrderBase"派生的实体,只有一个属性"Length"(int)。SongOrder与MusicOrder有多对一关系(即一个MusicOrder具有多个SonOrders)

快速概述:我想发布datamdel的图片,但我不被允许。。。关于数据模型的任何问题。

因此,现在我生成数据库,执行ddl脚本,并尝试运行以下代码:

using (DataContainer container = new DataContainer())
{
    MusicOrder musicOrder = new MusicOrder{Name = "Oldies", Quantity = 1};
    SongOrder songOrder = new SongOrder {Name = "Great balls of fire", Length = 240};
    songOrder.Details.Add(new Detail{Text = "Song from Jerry Lee Lewis"});
    songOrder.Comments.Add(new Comment{Text = "Cool song"});
    container.OrderBaseSet.AddObject(songOrder); //relevant line
    musicOrder.SongOrders.Add(songOrder);
    songOrder.Details.Clear();
    songOrder.Comments.Clear();
    container.OrderBaseSet.AddObject(musicOrder);
    container.SaveChanges();
}

在这种情况下,"SaveChanges"会导致一个异常,告诉我一些关于缺少外键关系的信息。。。

但是如果我移动

container.OrderBaseSet.AddObject(songOrder);

在"清除"之后-产生以下代码的部分:

using (DataContainer container = new DataContainer())
{
    MusicOrder musicOrder = new MusicOrder{Name = "Oldies", Quantity = 1};
    SongOrder songOrder = new SongOrder {Name = "Great balls of fire", Length = 240};
    songOrder.Details.Add(new Detail{Text = "Song from Jerry Lee Lewis"});
    songOrder.Comments.Add(new Comment{Text = "Cool song"});
    musicOrder.SongOrders.Add(songOrder);
    songOrder.Details.Clear();
    songOrder.Comments.Clear();
    container.OrderBaseSet.AddObject(songOrder); //relevant line
    container.OrderBaseSet.AddObject(musicOrder);
    container.SaveChanges();
}

一切都很好。

正如你所看到的,我知道如何绕过这个例外,我知道"双重添加"SongOrder是没有意义的。但我想知道这是一个bug还是一个功能。为什么在我的第一个例子中抛出异常。非常感谢您的全面解释。在我看来,实体框架也应该能够处理第一个例子,而不是抛出异常。所以我认为这是一个bug。

欢迎发表评论;)

Andi

实体框架外键跟踪导致问题

之所以会发生这种情况,是因为调用AddObject不会只添加单个实体,而是添加所有未附加到上下文的相关实体。因此,当您在第一个示例中调用AddObject(songOrder)时,您还添加了DetailComment。但在此之后,您可以在导航属性上调用Remove来删除DetialComment。附加实体上的Remove只会破坏关系,但不会从上下文中删除DetailComment(它只会将它们的主要关系设置为null),所以一旦您尝试调用SaveChanges,它就会爆炸,因为您试图在没有关联OrderBase的情况下保存DetailComment(我想关系是不可为null的)。

在第二个示例中,CommentDetail在向上下文添加顺序之前被删除,因此其行为符合预期。

这不是一个bug,而是一个"特性"。

您不必将歌曲顺序添加到基础中。只需将歌曲添加到音乐中,然后将音乐添加到基础音乐中即可。

最有可能的是不喜欢你添加与音乐无关的歌曲。