实体框架:多对多关系中的重复记录

时间:2012-07-25 09:08:04

标签: c# .net entity-framework ef-code-first

我有以下实体框架代码的第一个代码。创建表并插入数据。但是俱乐部表中有重复的记录。

我的运作是: -

  1. 使用分会创建应用创建分会

  2. 使用person app创建人员

  3. 如何避免重复录入?

    enter image description here

        static void Main(string[] args)
        {
            Database.SetInitializer<NerdDinners>(new MyInitializer());
    
            CreateClubs();
            InsertPersons();
    
        }
    
        public static void CreateClubs()
        {
    
            string connectionstring = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30";
            using (var db = new NerdDinners(connectionstring))
            {
    
                Club club1 = new Club();
                club1.ClubName = "club1";
    
                Club club2 = new Club();
                club2.ClubName = "club2";
    
                Club club3 = new Club();
                club3.ClubName = "club3";
    
                db.Clubs.Add(club1);
                db.Clubs.Add(club2);
                db.Clubs.Add(club3);
    
                int recordsAffected = db.SaveChanges();
    
    
            }
        }
    
        public static Club GetClubs(string clubName)
        {
            string connectionstring = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30";
            using (var db = new NerdDinners(connectionstring))
            {
    
                //var query = db.Clubs.Where(p => p.ClubName == clubName);
                var query = db.Clubs.SingleOrDefault(p => p.ClubName == clubName);
                return query;
            }
        }
    
        public static void InsertPersons()
        {
            string connectionstring = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30";
            using (var db = new NerdDinners(connectionstring))
            {
    
                Club club1 = GetClubs("club1");
                Club club2 = GetClubs("club2");
                Club club3 = GetClubs("club3");
    
                Person p1 = new Person();
                p1.PersonName = "Person1";
    
                Person p2 = new Person();
                p2.PersonName = "Person2";
    
                List<Club> clubsForPerson1 = new List<Club>();
                clubsForPerson1.Add(club1);
                clubsForPerson1.Add(club3);
    
                List<Club> clubsForPerson2 = new List<Club>();
                clubsForPerson2.Add(club2);
                clubsForPerson2.Add(club3);
    
                p1.Clubs = clubsForPerson1;
                p2.Clubs = clubsForPerson2;
    
                db.Persons.Add(p1);
                db.Persons.Add(p2);
    
                int recordsAffected = db.SaveChanges();
    
    
            }
        }
    

    public class Person
    {
        public int PersonId { get; set; }
        public string PersonName { get; set; }
        public virtual ICollection<Club> Clubs { get; set; }
    }
    
    public class Club
    {
        public int ClubId { get; set; }
        public string ClubName { get; set; }
        public virtual ICollection<Person> Members { get; set; }
    }
    
    //System.Data.Entity.DbContext is from EntityFramework.dll
    public class NerdDinners : System.Data.Entity.DbContext
    {
    
        public NerdDinners(string connString): base(connString)
        { 
    
        }
    
        protected override void OnModelCreating(DbModelBuilder modelbuilder)
        {
             //Fluent API - Plural Removal
            modelbuilder.Conventions.Remove<PluralizingTableNameConvention>();
        }
    
        public DbSet<Person> Persons { get; set; }
        public DbSet<Club> Clubs { get; set; }
    
    }
    

2 个答案:

答案 0 :(得分:18)

问题在于您创建了更多的上下文。

首先你创建了俱乐部。没关系。但是当你创建人员时,你会通过GetClubs获取俱乐部,但是对于每个俱乐部,你都会处理实际的实体框架上下文,这样你最终会得到分离的实体。在InsertPersons,您将新的俱乐部实体添加到新人中,因此实际情况会认为俱乐部是新的俱乐部。

因此,当您向某个人添加一个俱乐部时,您实际上会创建新的俱乐部。

这是因为实体框架跟踪变更并管理每个上下文的实体。如果您将实体添加到尚未包含它的上下文中,那么它将被视为一个新实体。

实际上,你应该做这样的事情(未经测试):

static void Main(string[] args)
{
    Database.SetInitializer<NerdDinners>(new MyInitializer());

    string connectionstring = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30";
    using (var db = new NerdDinners(connectionstring))
    {
        CreateClubs(db);
        InsertPersons(db);
    }

}

public static void CreateClubs(NerdDinners db)
{
    Club club1 = new Club();
    club1.ClubName = "club1";

    Club club2 = new Club();
    club2.ClubName = "club2";

    Club club3 = new Club();
    club3.ClubName = "club3";

    db.Clubs.Add(club1);
    db.Clubs.Add(club2);
    db.Clubs.Add(club3);

    int recordsAffected = db.SaveChanges();
}

public static Club GetClubs(string clubName, NerdDinners db)
{
    //var query = db.Clubs.Where(p => p.ClubName == clubName);
    var query = db.Clubs.SingleOrDefault(p => p.ClubName == clubName);
    return query;
}

public static void InsertPersons(NerdDinners db)
{
    Club club1 = GetClubs("club1", db);
    Club club2 = GetClubs("club2", db);
    Club club3 = GetClubs("club3", db);

    Person p1 = new Person();
    p1.PersonName = "Person1";

    Person p2 = new Person();
    p2.PersonName = "Person2";

    List<Club> clubsForPerson1 = new List<Club>();
    clubsForPerson1.Add(club1);
    clubsForPerson1.Add(club3);

    List<Club> clubsForPerson2 = new List<Club>();
    clubsForPerson2.Add(club2);
    clubsForPerson2.Add(club3);

    p1.Clubs = clubsForPerson1;
    p2.Clubs = clubsForPerson2;

    db.Persons.Add(p1);
    db.Persons.Add(p2);

    int recordsAffected = db.SaveChanges();
}

当然你应该重构这段代码的结构,但请注意我的操作只使用一个EF上下文。

答案 1 :(得分:0)

感谢@PeterPorfy

另请阅读Exception of type 'System.ObjectDisposedException'

我用过

 ((IObjectContextAdapter)db).ObjectContext.Attach((IEntityWithKey)entity); 

用于附加上一个上下文中的对象。

我使用的IEntityWithKey的一个例子如下。如果您发现此方法存在任何问题,请发表评论。

public class Person : IEntityWithKey
{
    public int PersonId { get; set; }
    public string PersonName { get; set; }

    public EntityKey EntityKey { get; set; }
}

请参阅以下内容

  1. Problem with SaveChanges() Entity Framework 4.1
  2. Entity Framework Updating Many-To-Many Relationships - POCO