C# Ef 6.0多对多插入这么多编码。。。为什么?
我的问题是为什么ef 6.0不支持忽略重复项 让我们举一个例子: 我有两张桌子C# Ef 6.0多对多插入这么多编码。。。为什么?,c#,sql-server,entity-framework,C#,Sql Server,Entity Framework,我的问题是为什么ef 6.0不支持忽略重复项 让我们举一个例子: 我有两张桌子 应用程序{id,AppName} AdGroup{id,GroupName} 应用程序与AdGroup之间存在多对多的关系。现在,每次添加带有广告组的应用程序时,我都需要首先执行以下操作以避免重复的密钥插入: 检查应用程序是否已经存在 检查指定的ADGroups是否已存在 找出差异 更新数据库 为了插入一段血淋淋的关系,这似乎需要做很多工作。可以编写sql查询来执行插入中的选择,以确保数据不存在,然后执行插入。它将根
//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");
});
//应用程序和父组之间的关系
modelBuilder.Entity()
.HasMany(s=>s.Groups)
.WithMany(a=>a.Applications)
.Map(cs=>
{
cs.MapLeftKey(“申请”);
cs.MapRightKey(“AdGroup”);
cs.ToTable(“应用程序组”);
});
编辑
下面是我用来插入关系的代码示例:
使用(var db=new ARContext())
{
var val=新应用程序
{
Application=“CRM”,
组=新列表{
新的AdGroup{Group=“CRM_ADMIN”},
新的AdGroup{Group=“CRM_-1”},
新的AdGroup{Group=“CRM_-2”},
}
};
var dbArr=db.Applications.Where(a=>a.Application==val.Application).FirstOrDefault();
if(dbArr==null)
{
添加(新应用程序(){Application=val.Application});
db.SaveChanges();
}
dbArr=db.Applications.Where(a=>a.Application==val.Application).FirstOrDefault();
if(dbArr.Groups==null)
{
dbArr.Groups=新列表();
}
foreach(变量组中的变量gr)
{
var dbGrp=db.Groups.Where(g=>g.Group==gr.Group).FirstOrDefault();
if(dbGrp==null)
{
dbArr.Groups.Add(gr);
}
其他的
{
dbArr.Groups.Add(dbGrp);
}
}
db.SaveChanges();
}
上面使用的名称和代码示例有一些不同之处,但要点是
因此,首先我需要保存新的应用程序,然后通过各个组查看它们是否存在,并相应地添加到上下文中。这是除了编写存储过程之外的唯一方法吗
谢谢像这样的东西也应该起作用:
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();
}
使用(var db=new ARContext())
{
var groupNames=new[]{“CRM_管理”、“CRM_精品店1”、“CRM_精品店2”};
//获取应用程序(已加载),如果它存在,则创建一个新的应用程序
var application=db.Applications.Include(a=>a.AdGroups)
.FirstOrDefault(a=>a.Application==“CRM”)
??db.Add(新应用程序{Application=“CRM”});
//如果应用程序尚不存在,请初始化AdGroup集合
//不过,最好在应用程序模型的构造函数中这样做
if(db.Entry(application.State==EntityState.Added)
application.AdGroups=新列表();
//迭代不属于application.Adgroup集合的组名
foreach(groupNames.Where(g=>!application.AdGroups.Any(ag=>ag.GroupName==g))中的变量名)
{
AdGroup group=db.AdGroups.FirstOrDefault(ag=>ag.GroupName==name)
??db.Add(新的AdGroup{GroupName=name});
application.AdGroups.Add(组);
}
db.SaveChanges();
}
您的示例有点不寻常,因为您对
应用程序
、AdGroup
或它们之间的关系一无所知,这会导致代码中出现大量检查。首先,如果应用程序存在(包括AdGroups
到Eager load
),我将从数据库中获取该应用程序,否则我将创建一个新的应用程序。如果我必须创建一个新集合,则应该初始化AdGroup
集合(除非您在模型的构造函数中这样做)。最后,迭代不在集合应用程序.AdGroups
中的组名。如果该组存在,则获取该组,如果不存在,则创建该组并将其添加到Application.AdGroups
你能展示你的地图吗?如果映射正确,EF不应该插入重复项,所以不需要检查记录是否存在或存在anything@Alexander:我不是说它在插入重复项。我是说它不必要地抱怨重复插入。我对各个列都有唯一的限制。你不是使用fluent api.Map
方法吗?你确定你有正确的左右键吗?@wickd如果你想添加一个应用程序,你必须从数据库中获取与之对应的adgroup(或者先在数据库中创建它们),将它们分配给应用程序,然后只添加应用程序。不知道任何事情的原因是,我假设一个无状态的pov。因此,如果1个客户端删除了
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();
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();
}