C# 添加到多对多关系表会在db中生成重复的值
我有三个表zRequest、zFacility和一个表,用于两个表之间的多对多关系,每个表的id都是。我的目标是添加一个包含许多设施的请求。但是,每当我添加带有某些设施的新请求时,它都会将所选设施添加到zFacility以及关系表中 这是控制器中的相关代码:C# 添加到多对多关系表会在db中生成重复的值,c#,asp.net-mvc,database,entity-framework,C#,Asp.net Mvc,Database,Entity Framework,我有三个表zRequest、zFacility和一个表,用于两个表之间的多对多关系,每个表的id都是。我的目标是添加一个包含许多设施的请求。但是,每当我添加带有某些设施的新请求时,它都会将所选设施添加到zFacility以及关系表中 这是控制器中的相关代码: foreach (var facility in Facilities) { var facName = facility.Replace(".", " "); var facQry = from fac in db.zFa
foreach (var facility in Facilities)
{
var facName = facility.Replace(".", " ");
var facQry = from fac in db.zFacilities where fac.FacilityName == facName select fac;
var facList = facQry.ToList();
var item = new zFacility();
item.FacilityId = facList.FirstOrDefault().FacilityId;
item.FacilityName = facList.FirstOrDefault().FacilityName;
//db.zFacility.Attach(item);
zrequest.zFacility.Add(item);
}
zrequestRepository.InsertOrUpdate(zrequest);
zrequestRepository.Save();
我做了一些研究,并尝试通过注释行将每个工具连接到数据库,但这给了我另一个错误,因为相同类型的另一个实体已经具有相同的主键值
这是zRequestRepository中的代码:
public void InsertOrUpdate(zRequest zrequest)
{
if (zrequest.RequestId == default(int)) {
// New entity
context.zRequests.Add(zrequest);
} else {
// Existing entity
context.Entry(zrequest).State = System.Data.Entity.EntityState.Modified;
}
}
我能做些什么来解决这个问题?如果我需要提供更多信息,请告诉我
编辑,按要求提供相关模型。
zFacility:
using System;
using System.Collections.Generic;
public partial class zFacility
{
public zFacility()
{
this.zRequest = new HashSet<zRequest>();
this.zRoom = new HashSet<zRoom>();
}
public short FacilityId { get; set; }
public string FacilityName { get; set; }
public virtual ICollection<zRequest> zRequest { get; set; }
public virtual ICollection<zRoom> zRoom { get; set; }
}
使用系统;
使用System.Collections.Generic;
公共部分类zFacility
{
公共设施
{
this.zRequest=new HashSet();
this.zRoom=new HashSet();
}
公共短设施ID{get;set;}
公共字符串设施名称{get;set;}
公共虚拟ICollection zRequest{get;set;}
公共虚拟ICollection zRoom{get;set;}
}
zRequest:
using System;
using System.Collections.Generic;
public partial class zRequest
{
public zRequest()
{
this.zFacility = new HashSet<zFacility>();
this.zRoom = new HashSet<zRoom>();
}
public int RequestId { get; set; }
public string ModCode { get; set; }
public short StatusId { get; set; }
public int WeekId { get; set; }
public short DayId { get; set; }
public short PeriodId { get; set; }
public short SessionLength { get; set; }
public short Semester { get; set; }
public short RoundNo { get; set; }
public string SpecialRequirement { get; set; }
public short UserId { get; set; }
public virtual zDay zDay { get; set; }
public virtual zPeriod zPeriod { get; set; }
public virtual zRound zRound { get; set; }
public virtual zStatus zStatus { get; set; }
public virtual zWeek zWeek { get; set; }
public virtual ICollection<zFacility> zFacility { get; set; }
public virtual ICollection<zRoom> zRoom { get; set; }
public virtual zUser zUser { get; set; }
}
使用系统;
使用System.Collections.Generic;
公共部分类zRequest
{
公共要求
{
this.zFacility=new HashSet();
this.zRoom=new HashSet();
}
public int RequestId{get;set;}
公共字符串ModCode{get;set;}
公共短状态ID{get;set;}
public int WeekId{get;set;}
公共短DayId{get;set;}
公共短周期ID{get;set;}
公共短会话长度{get;set;}
公共短学期{get;set;}
公共短循环号{get;set;}
公共字符串特殊要求{get;set;}
公共短用户标识{get;set;}
公共虚拟zDay zDay{get;set;}
公共虚拟zPeriod zPeriod{get;set;}
公共虚拟zRound{get;set;}
公共虚拟zStatus zStatus{get;set;}
公共虚拟zWeek zWeek{get;set;}
公共虚拟ICollection zFacility{get;set;}
公共虚拟ICollection zRoom{get;set;}
公共虚拟zUser zUser{get;set;}
}
它们都是首先通过数据库生成的。您需要做的是从数据库中选择ZFactorys对象,而不是为它们中的每一个创建新对象,因为这使EF认为您想要创建一个全新的记录 因此: 选择zFactories 将它们添加到zRequest.zFacility中(如果它们尚未存在)
保存回答这个问题有点困难,因为代码中有一些漏洞。根据使用情况,我假设
Facilities
是一个可枚举的字符串,并且是从post数据中的选定项创建的
我不知道为什么要创建一个新的zFacility
,而不是使用已经从数据库中提取的工具。按照您现在的方式,如果没有匹配工具,您还引入了空引用异常的可能性
无论如何,我会更改代码,您必须:
// This is so you can run a single minimal query to select
// all the facilities you'll be working with
var facNames = Facilities.Select(m => m.Replace(".", " "));
var facList = db.zFacilities.Where(m => facNames.Contains(m.FacilityName)).ToList();
// Now add all facilities not currently attached
facList.Where(m => !zrequest.zFacility.Contains(m)).ToList()
.ForEach(m => zrequest.zFacility.Add(m));
您可能还需要删除已取消选择的项目。最简单的方法是反向执行最后一位代码:
zrequest.zFacility.Where(m => !facList.Contains(m)).ToList()
.ForEach(m => zrequest.zFacility.Remove(m));
编辑
实际上,删除取消选择的项目的更简洁的方法是:
zrequest.zFacility.RemoveAll(m => !factList.Contains(m));
默认情况下,EF假定所选设施(zFacility)是新的,并将其插入数据库 为了避免这种情况,您需要将zFacility的状态更改为
Unchanged
像这样的
public void InsertOrUpdate(zRequest zrequest)
{
if (zrequest.RequestId == default(int)) {
context.zFacility.Attach(zrequest); // state Unchanged for zFacility
// New entity
context.zRequests.Add(zrequest);
} else {
// Existing entity
context.Entry(zrequest).State = System.Data.Entity.EntityState.Modified;
}
}
你能发布你的模型吗?@Alundrathedreamwalker,这些模型已经添加到原始帖子中。你在foreach的设施(设施中的var设施)来自哪里?您确定它们来自同一对象上下文吗?Facility是一个字符串数组,包含所选设施的FacilityName。这是从视图中获得的。我不确定你所说的“同一对象上下文”是什么意思……我认为这一个对解决我遇到的问题帮助最大。我不得不稍微修改你的代码,因为
context.zRequests.Add()
只接受zFacility类型的对象,所以我循环了zrequest中的工具,并将它们一个接一个地连接起来。我计划使用此代码来改进我的方法并使其更有效,但我不完全理解。。。你能解释一下最后两行吗?