Entity framework foreign key tracking causes problem
working with EF4, model first approach in VS 2010:
Consider the following EntityModel:
"OrderBase" is an abstract entity with just one property "Name"
"Detail" (with one property "Text") is an entity that has a many to one association to "OrderBase" (i.e. one OrderBase has multiple Details)
"Comment" (with one property "Text") is an entity that has a many to one association to "OrderBase" (i.e. one OrderBase has multiple Comments)
"MusicOrder" is an entity derived from "OrderBase" with just one property "Quantity" (int)
"SongOrder" is an entity derived from "OrderBase" with just one property "Length" (int). SongOrder has a many to one relation to MusicOrder (i.e. one MusicOrder has multiple SonOrders)
For a quick overview: Wanted to post the image of the datamdel, but I'm not allowed... So any questions concerning the datamodel.
So now I generate my database, execute the ddl script and try to run the following code:
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();
}
In this case "SaveChanges" leads to an exception telling me something about missing foreign key relations...
But if I move the line
container.OrderBaseSet.AddObject(songOrder);
after the "Clear"-part resulting in the following code:
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();
}
everything works fi开发者_如何转开发ne.
As you can see I know how to come around the exception and I know it makes no sense to "double add" the SongOrder. But I'm wondering if this is a bug or a feature. Why is the exception thrown in my first example. Would really appreciate a comprehensive explanation. In my opinion, the entity framework should also be able to deal with the first example and not throw an exception. So I would say it's a bug.
Feel free to comment ;)
Andi
This happens because calling AddObject
doesn't add only single entity but all related entities which are not attached to the context as well. So when you call AddObject(songOrder)
in the first example you also add Detail
and Comment
. But after that you call Remove
on navigation properties to remove both Detial
and Comment
. Remove
on attached entities will only break the relation but it will not delete Detail
and Comment
from the context (it will only set their principal relation to null) so once you try calling SaveChanges
it will blow up because you are trying to save Detail
and Comment
without associated OrderBase
(I guess relations are non nullalbe).
In the second example Comment
and Detail
is deleted before you add order to the context so it behaves as expected.
It is not a bug it is a "feature".
you dont have to add songorder to base. just add song to music and then music to base.
Its most prob not liking you adding song thats not associated with music.
精彩评论