Ef 6.0多对多插入如此多的编码..为什么?

本文关键字:编码 为什么 插入 Ef | 更新日期: 2023-09-27 18:27:39

我的问题更多的是为什么ef 6.0不支持忽略重复项?

让我们举一个例子:

我有两张桌子

  1. 应用程序{id,AppName}
  2. AdGroup{id,GroupName}

应用程序与ADGroups之间存在多对多关系。现在,每次我添加带有广告组的应用程序时,我都需要首先执行以下操作以避免重复的密钥插入:

  1. 检查应用程序是否已存在
  2. 检查指定的ADGroups是否已存在
  3. 找出差异
  4. 更新数据库

这似乎只是为了插入一段血腥的关系而做的大量工作。可以编写一个sql查询来在插入中进行选择,以确保数据不在那里,然后执行插入。它将返回0或1,这取决于行是否已经存在

假设n到n表将被称为Applications_AdGroup

然后,插入关系的查询将是这样的(未测试):

Insert Into Applications (AppName)
   select 'CRM'
      where NOT EXISTS(
         select 1
         from Applications
         where AppName = 'CRM'
      )
Insert Into AdGroup (GroupName)
   select 'CRM_ADMIN'
      where NOT EXISTS(
         select 1
         from Applications
         where AppName = 'CRM_ADMIN'
      )
Insert Into Applications_AdGroup (id_adgroup, id_applications)
    select
       adgroup.id,
       applications.id
    from
       adgroup,
       applications
    where
       adgroup.GroupName = 'CRM_ADMIN' AND
       applications.AppName = 'CRM' AND
       WHERE NOT EXISTS (
          select 1
          from
             Applications_Adgroup
          where
             Applications_AdGroup.id_adgroup = adgroup.id AND
             Applications_AdGroup.id_applications = applications.id
       )

因此,基本上,即使应用程序、广告组或关系已经存在,它也不会插入任何内容。。。

一天结束时,将对数据库进行一个简单的调用。Applications.Add(obj),然后保存更改。所有的检查都是在后台进行的,一切都好吗?

对此有何看法?我只是做错了吗?

编辑我想用ef的方式做这件事会有一些并发问题。在上述4个步骤中的任何一个过程中,另一个过程都可能插入AdGroup,并且无论如何都会出现重复的密钥错误

编辑以下为映射:

//Relation between Application and the Parent Group
            modelBuilder.Entity<Applications>()
                .HasMany<AdGroup>(s => s.Groups)
                .WithMany(a => a.Applications)
                .Map(cs =>
                    {
                        cs.MapLeftKey("Application");
                        cs.MapRightKey("AdGroup");
                        cs.ToTable("Application_Groups");
                    });

编辑下面是我用来插入关系的代码示例:

使用(var db=new ARContext()){

var val = new Applications
{
    Application = "CRM",
    Groups = new List<AdGroup> {
        new AdGroup { Group = "CRM_ADMIN" },
        new AdGroup { Group = "CRM_Boutique1" },
        new AdGroup { Group = "CRM_Boutique2" },
    }
};
var dbArr = db.Applications.Where(a => a.Application == val.Application).FirstOrDefault();
if (dbArr == null)
{
    db.Applications.Add(new Applications() { Application = val.Application });
    db.SaveChanges();
}
dbArr = db.Applications.Where(a => a.Application == val.Application).FirstOrDefault();
if (dbArr.Groups == null)
{
    dbArr.Groups = new List<AdGroup>();
}
foreach (var gr in val.Groups)
{
    var dbGrp = db.Groups.Where(g => g.Group == gr.Group).FirstOrDefault();
    if (dbGrp == null)
    {
        dbArr.Groups.Add(gr);
    }
    else
    {
        dbArr.Groups.Add(dbGrp);
    }
}
db.SaveChanges();

}

上面使用的名称和代码示例有一些差异,但要点就在那里。。。

因此,首先我需要保存新的应用程序,然后处理各个组,看看它们是否存在,并相应地添加到上下文中。这是除了编写存储过程之外的唯一方法吗??

感谢

Ef 6.0多对多插入如此多的编码..为什么?

类似的东西也应该起作用:

using(var db = new ARContext())
{
  var groupNames = new[] {"CRM_ADMIN","CRM_Boutique1","CRM_Boutique2"};
  //Fetch application (AdGroups eager loaded) if it exists, otherwise create a new one
  var application = db.Applications.Include(a => a.AdGroups)
                                   .FirstOrDefault(a => a.Application == "CRM") 
                                   ?? db.Add(new Application { Application = "CRM" });
  //If the application didn't exist yet, initialize the AdGroup collection
  //Better to do this in the constructor of your application model though
  if(db.Entry(application).State == EntityState.Added)
     application.AdGroups = new List<AdGroup>();
  //Iterate over groupNames that are not part of application.Adgroup's collection           
  foreach(var name in groupNames.Where(g => !application.AdGroups.Any(ag => ag.GroupName == g)))
  {
      AdGroup group = db.AdGroups.FirstOrDefault(ag => ag.GroupName == name) 
                      ?? db.Add(new AdGroup { GroupName = name });
      application.AdGroups.Add(group);
  }
  db.SaveChanges();     
}

但是,您的示例有点不寻常,因为您对ApplicationAdGroup或它们之间的关系一无所知,这会导致代码中出现大量检查。首先,如果应用程序存在(包括AdGroupsEager Loading),我会从数据库中获取它,否则我会创建一个新的应用程序。如果我必须创建一个新的集合,AdGroup集合应该被初始化(除非您在模型的构造函数中这样做)。最后,对不在集合Application.AdGroups中的组名进行迭代。如果组存在,则获取它;如果不存在,则创建它并将其添加到Application.AdGroups中。