Complex Entity Framework linked-graphs issue: how to limit change set / break the graph?
- by Hightechrider
I have an EDMX containing Sentences, and Words, say and a Sentence contains three Words, say. Appropriate FK relationships exist between the tables.
I create some words: Word word1 = new Word(); Word word2 = ...
I build a Sentence: Sentence x = new Sentence (word1, word2, word3);
I build another Sentence: Sentence y = new Sentence (word1, word4, word5);
I try to save x to the database, but EF builds a change set that includes everything, including y, word4 and word5 that aren't ready to save to the database. When SaveChanges() happens it throws an exception: Unable to determine the principal end of the ... relationship. Multiple added entities may have the same primary key.
I think it does this because Word has an EntityCollection<Sentence> on it from the FK relationship between the two tables, and thus Sentence y is inextricably linked to Sentence x through word1.
So I remove the Navigation Property Sentences from Word and try again. It still tries to put the entire graph into the change set.
What suggestions do the Entity Framework experts have for ways to break this connection. Essentially what I want is a one-way mapping from Sentence to Word; I don't want an EntityCollection<Sentence> on Word and I don't want the object graph to get intertwined like this.
Code sample:
This puts two sentences into the database because Verb1 links them and EF explores the entire graph of existing objects and added objects when you do Add/SaveChanges.
Word subject1 = new Word(){ Text = "Subject1"};
Word subject2 = new Word(){ Text = "Subject2"};
Word verb1 = new Word(){ Text = "Verb11"};
Word object1 = new Word(){ Text = "Object1"};
Word object2 = new Word(){ Text = "Object2"};
Sentence s1 = new Sentence(){Subject = subject1, Verb=verb1, Object=object1};
Sentence s2 = new Sentence(){Subject=subject2, Verb=verb1, Object=object2};
context.AddToSentences(s1);
context.SaveChanges();
foreach (var s in context.Sentences)
{
Console.WriteLine(s.Subject + " " + s.Verb + " " + s.Object);
}