c# – 更新Entity Framework 6中的多对多导航属性,更改不保存

前端之家收集整理的这篇文章主要介绍了c# – 更新Entity Framework 6中的多对多导航属性,更改不保存前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我现在已经把我的头发拉了大约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();

        }
    }

猜你在找的C#相关文章