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

时间:2011-06-01 09:43:36

标签: c# .net entity-framework

使用EF4,VS 2010中的模型第一种方法:

考虑以下EntityModel:

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

“详细信息”(带有一个属性“Text”)是与“OrderBase”具有多对一关联的实体(即一个OrderBase具有多个详细信息)

“Comment”(带有一个属性“Text”)是一个与“OrderBase”有多对一关联的实体(即一个OrderBase有多个注释)

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

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

快速浏览: 想发布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是没有意义的。但我想知道这是一个错误还是一个功能。为什么在我的第一个例子中抛出异常。真的很感激全面的解释。在我看来,实体框架也应该能够处理第一个例子,而不是抛出异常。所以我会说这是一个错误。

随意评论;)

岸堤

2 个答案:

答案 0 :(得分:1)

你没有必要添加歌曲订单到基地。只需将歌曲添加到音乐中,然后将音乐添加到基础。

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

答案 1 :(得分:1)

这是因为调用AddObject不会仅添加单个实体,而是添加所有未附加到上下文的相关实体。因此,当您在第一个示例中致电AddObject(songOrder)时,您还会添加DetailComment。但之后,您在导航属性上调用Remove以删除DetialComment。附加实体上的Remove只会破坏关系,但不会从上下文中删除DetailComment(它只会将它们的主关系设置为null)所以一旦你尝试调用{{ 1}}它会爆炸,因为您试图保存SaveChangesDetail而没有关联Comment(我猜关系不是nullalbe)。

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

这不是一个“功能”的错误。