无法更新实体框架许多一对多的关系 [英] Cannot update many-to-many relationships in Entity Framework

查看:111
本文介绍了无法更新实体框架许多一对多的关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用实体框架4.3代码首先,我有更新许多一对多的关系问题。



我定义了以下类:



 公共抽象类的实体
{
[列(订单= 0)
[关键]
公众诠释标识{搞定;组; }

[时间戳]
[列(订单= 1)]
公众的byte []版本{搞定;组; }
}


公共类视频:实体
{
公共字符串名称{搞定;组; }
公共字符串描述{搞定;组; }
公开时间跨度长{搞定;组; }

公共虚拟的ICollection<&同事GT;同事{搞定;组; }
}


公共类同事:实体
{
公共字符串名字{获得;组; }
公共字符串名字{获得;组; }
公共虚拟的ICollection<视频>影片{搞定;组; }
}

在创建数据库,架构看的权利:
有一个视频,同事和VideoCoworkers表也没有。



我使用存储库模式在N层应用程序访问数据库,我的插入和更新方法如下:

 公共牛逼插入(T实体)
{
//创建数据库环境。当其配置,它调用context.SaveChanges()使用
(VAR会话=新的DatabaseSession())
{
session.Context.Set< T>()添加(实体);
}
}

公共T更新的(T实体)
{
//创建数据库环境。当其配置,它调用context.SaveChanges()使用(VAR会话=新的DatabaseSession())
{
实体= session.Context.Set<
; T>()将(实体);
session.Context.Entry(实体).STATE = EntityState.Modified;
}
返回实体;
}

当我更新的实体,我创建一个DTO实体对象,这是为什么使用DbSet.Attach,而不是选择它和更新性质一个接一个



当我初始化数据库,我想补充一些测试数据:




  1. 创建3同事,在这里我设置的姓氏和名字。 (A,B,C)

  2. 创建3视频,在这里我设置标题,描述和长度,还设置了一些同事。第一视频有A,B,第二个有B,C和第三个拥有A,C。



在我列出的影片从代码中,我可以看到Video.Coworkers收集充满了良好的价值观,当我在SQL Server Management Studio中查询链接表(VideoCoworkers),它看起来也不错。



我的问题是 $ b $当我更新例如视频的标题b,它的工作原理。但是,当我试图从视频2删除现有的同事(B和C),并尝试添加同事A,那么关系不会被更新。同时,当我只尝试添加新的同事,或者只尝试删除一个不能正常工作。我创建一个由与同事的一个新的集合(这是从数据库查找()凭身份证法选择)创建一个新的视频实体用作Update()方法的参数的实体。



什么是更新许多一对多关系的正确方法?


解决方案

但是,当我试图从视频2删除现有的同事(B和C),
和尝试添加同事A,那么关系不会被更新。




如果不使用通用的存储库中的正确程序是

 使用(VAR会话=新的DatabaseSession())
{
视频2 = session.Context。设置<视频方式>()包含(v => v.Coworkers)
。单(v => v.Id == video2Id);

coworkerA =新同事{ID = coworkerAId};
session.Context.Set<同事方式>()将(coworkerA);

video2.Coworkers.Clear();
video2.Coworkers.Add(coworkerA)

session.Context.SaveChanges();
}



关键部分是,你必须加载或附加实体在其原始状态,改变实体,即删除和添加的孩子,然后保存更改。 EF的变化检测将创造必要的插入和删除的链接表项的语句。简单的过程状态设置为修改您想在您的泛型更新方法仅适用于更新标性质 - 如更改视频节目 - 但不会更新实体之间的关系的工作。


I am using Entity Framework 4.3 Code First, and I have problem with updating many-to-many relationships.

I defined the following classes:

public abstract class Entity
{
    [Column(Order = 0)]
    [Key]
    public int Id { get; set; }

    [Timestamp]
    [Column(Order = 1)]
    public byte[] Version { get; set; }
}


public class Video : Entity
{
    public string Title { get; set; }
    public string Description { get; set; }
    public TimeSpan Length { get; set; }

    public virtual ICollection<Coworker> Coworkers { get; set; }
}


public class Coworker : Entity
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public virtual ICollection<Video> Videos { get; set; }
}

When the database is created, the schema look right: There is a Videos, Coworkers and VideoCoworkers table too, without

I use repository pattern in an N-Tier application to access database, my Insert and Update method looks like this:

public T Insert(T entity)
{
    //Creates database context. When it disposes, it calls context.SaveChanges()
    using (var session = new DatabaseSession())
    {
        session.Context.Set<T>().Add(entity);
    }
}

public T Update(T entity)
{
    //Creates database context. When it disposes, it calls context.SaveChanges()
    using (var session = new DatabaseSession())
    {
        entity = session.Context.Set<T>().Attach(entity);
        session.Context.Entry(entity).State = EntityState.Modified;
    }
    return entity;
}

When I update an entity, I create the entity object from a DTO, that's why use DbSet.Attach instead of selecting it and updating the properties one-by-one.

When I initialize the database, I add some test data:

  1. Create 3 Coworkers, where I set first and last name. (A, B, C)
  2. Create 3 Videos, where I set title, description and length, and also set some coworkers. First video has A,B, second has B,C and third has A,C.

When I list the Videos from code, I can see that Video.Coworkers collection is filled with good values, and when I query the link table (VideoCoworkers) in SQL Server Management Studio, it also looks good.

My problem is when I update for example the title of the Video, it works. But when I try to delete from Video2 the existing coworkers (B and C), and try to add coworker A, then the relationship is not updated. It also does not work when I only try to add new coworker, or only try to delete one. I create the entity which is used as the parameter of the Update() method by creating a new Video entity with a new collection of Coworkers (which are selected from the database with Find() method by Id).

What is the correct way to update many-to-many relationships?

解决方案

But when I try to delete from Video2 the existing coworkers (B and C), and try to add coworker A, then the relationship is not updated.

Without using a generic repository the correct procedure would be:

using (var session = new DatabaseSession())
{
    video2 = session.Context.Set<Video>().Include(v => v.Coworkers)
        .Single(v => v.Id == video2Id);

    coworkerA = new Coworker { Id = coworkerAId };
    session.Context.Set<Coworker>().Attach(coworkerA);

    video2.Coworkers.Clear();
    video2.Coworkers.Add(coworkerA)

    session.Context.SaveChanges();
}

The essential part is that you must load or attach the entity in its original state, change the entity, i.e. remove and add children, and then save the changes. EF's change detection will create the necessary INSERT and DELETE statements for the link table entries. The simple procedure to set the state to Modified you are trying in your generic Update method is suited only for updating scalar properties - like changing the video title - but won't work for updating relationships between entities.

这篇关于无法更新实体框架许多一对多的关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆