我现在已经把我的头发拉了大约2天,因为当我向现有实体添加一个多对多的实体时,我根本无法获得EF保存更改.
我的结构很简单:
>我有一个名为Person的表,它有一个ID(主,身份)和一些其他字符串字段
>一个称为关键字的表,其中包含ID(主,身份)和名为Value的字符串字段
>和一个PersonKeywordRelation,一个PersonId和一个KeywordId字段
当我生成我的实体(数据库首先),我得到一个类Person,ICollection<关键字> – 一切都好,按预期工作.
当我尝试保存一个现有的人,修改的关键字列表出现问题.只保存标量属性(字符串),而不是我的关键字!
>我试过禁用Lazy Loading,没有任何效果.
>我尝试再次从数据库中加载每个关键字,没有任何效果.
>我尝试将所有关键字加载到上下文中,以查看是否有助于EF检测更改,但没有.
我很确定我不是唯一有这个问题的人(事实上,我完全确定,因为我已经在同一主题上看到过几个问题,但我无法找到工作答案. ..),主要是对于旧版本的EF,这是另一个很好的理由,为什么我开始另一个问题:没有改变,解决这个问题在所有?
这是我的代码,用于更新(和创建)人员.您会注意到我尝试使EF保存更改相应.
public void SavePersons(IList<Person> persons) { // Create a EF Context using (var ctx = new MyDbEntities()) { foreach (var person in persons) { // Attach ctx.Persons.Attach(person); // Insert or update? ctx.Entry(person).State = person.Id == 0 ? EntityState.Added : EntityState.Modified; // Get current keywords before clearing from entity var keywords = new List<Keyword>(person.Keywords); // Clear keywords from entity,so we can add fresh ones,hopefully // EF will have an easier time handling this.. person.Keywords.Clear(); // Add keywords keywords.ForEach(kw => { ctx.Keywords.Attach(kw); ctx.Entry(kw).State = EntityState.Modified; person.Keywords.Add(kw); }); } // Save ctx.SaveChanges(); } }
解决方法
最后我终于可以休息了!我找到了解决方案!这不是一个漂亮的,但它的作品!
这肯定是我最后一次使用实体框架.导致更多的疼痛痛苦比好.
public void SavePersons(IList<Person> persons) { // Create a EF Context using (var ctx = new MyDbEntities()) { // Iterate foreach (var person in persons) { // Get current keywords var keywords = new List<Keyword>(person.Keywords).ToList(); // Fetch Person from DB (if its not a NEW entry). Must use Include,else it's not working. var newPerson = ctx.Persons .Include("Keywords") .FirstOrDefault(s => s.Id == person.Id) ?? person; // Clear keywords of the object,else EF will INSERT them.. Silly. newPerson.Keywords.Clear(); // Insert or update? ctx.Entry(newPerson).State = newPerson.Id == 0 ? EntityState.Added : EntityState.Modified; // Apply new scalar values if(newPerson.Id != 0) { person.Id = newPerson.Id; ctx.Entry(newPerson).CurrentValues.SetValues(person); } // Iterate through all keywords foreach (var kw in ctx.Keywords) { // If the current kw exists in OUR list,add it // - if not,remove the relation from the DB. if (keywords.Any(k => k.Id == kw.Id)) { //ctx.Entry(kw).State = EntityState.Unchanged; ctx.Keywords.Attach(kw); newPerson.Keywords.Add(kw); } else newPerson.Keywords.Remove(kw); } } // Save ctx.SaveChanges(); } }