【发布时间】:2018-06-15 11:23:06
【问题描述】:
我正在尝试创建一个与其他实体有多对多关系的实体对象。关系如下所示。
public class Change {
// Change Form Fields
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ChangeId { get; set; }
public string ChangeTitle { get; set; }
public string ChangeType { get; set; }
public DateTime DateSubmitted { get; set; }
public DateTime TargetDate { get; set; }
//Many to Many Collections
public virtual ICollection<Change_CriticalBankingApp> Change_CriticalBankingApps { get; set; } = new List<Change_CriticalBankingApp>();
public virtual ICollection<Change_ImpactedBusiness> Change_ImpactedBusinesses { get; set; } = new List<Change_ImpactedBusiness>();
public virtual ICollection<Change_ImpactedService> Change_ImpactedServices { get; set; } = new List<Change_ImpactedService>();
public virtual ICollection<Change_TestStage> Change_TestStages { get; set; } = new List<Change_TestStage>();
public virtual ICollection<Change_TypeOfChange> Change_TypeOfChanges { get; set; } = new List<Change_TypeOfChange>();
而DbContext设置如下
public class ChangeContext : DbContext {
public ChangeContext(DbContextOptions<ChangeContext> options) : base(options) {
Database.Migrate();
}
public DbSet<Change> Change { get; set; }
public DbSet<TestStage> TestStage { get; set; }
public DbSet<TypeOfChange> TypeOfChange { get; set; }
public DbSet<CriticalBankingApp> CriticalBankingApp { get; set; }
public DbSet<ImpactedBusiness> ImpactedBusiness { get; set; }
public DbSet<ImpactedService> ImpactedService { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder) {
modelBuilder.Entity<Change_CriticalBankingApp>().HasKey(t => new { t.ChangeId, t.CriticalBankingAppId });
modelBuilder.Entity<Change_ImpactedBusiness>().HasKey(t => new { t.ChangeId, t.ImpactedBusinessId });
modelBuilder.Entity<Change_ImpactedService>().HasKey(t => new { t.ChangeId, t.ImpactedServiceId });
modelBuilder.Entity<Change_TestStage>().HasKey(t => new { t.ChangeId, t.TestStageId });
modelBuilder.Entity<Change_TypeOfChange>().HasKey(t => new { t.ChangeId, t.TypeOfChangeId });
}
}
我开始遇到问题的地方是我没有使用实体框架生成 Id,主键是 SQL Server 2012 中的一个身份,一旦插入完成,我就会得到它,而不是使用 GUID(它我读过几乎所有在 DBA 世界中都非常不受欢迎的地方)。
所以最终发生的事情是我要么尝试插入,它尝试插入多对多关系,联结表中的 changeId 为空(因为它尚未生成),或者当我尝试我所拥有的下面在一个 post 方法中进行插入和更新。它出错是因为 ChangeId 键值已被跟踪。这是我在下面尝试的。
控制器方法
public IActionResult CreateChange([FromBody] ChangeModel change) {
if (change == null) {
return BadRequest();
}
//Remove many to many from Change to insert without them (as this can't be done until primary key is generated.
List<Change_CriticalBankingAppModel> criticalApps = new List<Change_CriticalBankingAppModel>();
criticalApps.AddRange(change.Change_CriticalBankingApps);
List<Change_ImpactedBusinessModel> impactedBusinesses = new List<Change_ImpactedBusinessModel>();
impactedBusinesses.AddRange(change.Change_ImpactedBusinesses);
List<Change_ImpactedServiceModel> impactedServices = new List<Change_ImpactedServiceModel>();
impactedServices.AddRange(change.Change_ImpactedServices);
List<Change_TestStageModel> testStages = new List<Change_TestStageModel>();
testStages.AddRange(change.Change_TestStages);
List<Change_TypeOfChangeModel> changeTypes = new List<Change_TypeOfChangeModel>();
changeTypes.AddRange(change.Change_TypeOfChanges);
change.Change_CriticalBankingApps.Clear();
change.Change_ImpactedBusinesses.Clear();
change.Change_ImpactedServices.Clear();
change.Change_TestStages.Clear();
change.Change_TypeOfChanges.Clear();
//Map Change model to change entity for inserting
var changeEntity = Mapper.Map<Change>(change);
_changeRepository.AddChange(changeEntity);
if (!_changeRepository.Save()) {
throw new Exception("Creating change failed on save.");
}
var changetoReturn = Mapper.Map<ChangeModel>(changeEntity);
//Iterate through Many to many Lists to add generated changeId
foreach (var criticalApp in criticalApps) {
criticalApp.ChangeId = changetoReturn.ChangeId;
}
foreach (var impactedBusiness in impactedBusinesses) {
impactedBusiness.ChangeId = changetoReturn.ChangeId;
}
foreach (var impactedService in impactedServices) {
impactedService.ChangeId = changetoReturn.ChangeId;
}
foreach (var testStage in testStages) {
testStage.ChangeId = changetoReturn.ChangeId;
}
foreach (var changeType in changeTypes) {
changeType.ChangeId = changetoReturn.ChangeId;
}
//Add many to many lists back to change to update
changetoReturn.Change_CriticalBankingApps = criticalApps;
changetoReturn.Change_ImpactedBusinesses = impactedBusinesses;
changetoReturn.Change_ImpactedServices = impactedServices;
changetoReturn.Change_TestStages = testStages;
changetoReturn.Change_TypeOfChanges = changeTypes;
changeEntity = Mapper.Map<Change>(changetoReturn);
_changeRepository.UpdateChange(changeEntity);
if (!_changeRepository.Save()) {
throw new Exception("Updating change with many to many relationships failed on save.");
}
changetoReturn = Mapper.Map<ChangeModel>(changeEntity);
return CreatedAtRoute("GetChange",
new { changeId = changetoReturn.ChangeId },
changetoReturn);
}
相关存储库方法
public Change GetChange(int changeId) {
return _context.Change.FirstOrDefault(c => c.ChangeId == changeId);
}
public void AddChange(Change change) {
_context.Change.Add(change);
}
public void UpdateChange(Change change) {
_context.Change.Update(change);
}
public bool ChangeExists(int changeId) {
return _context.Change.Any(c => c.ChangeId == changeId);
}
我知道,如果我让实体框架生成 guid 而不是让数据库生成身份 int,我会更轻松地使用它,但这个项目的要求是不使用 Guid。
任何有关如何成功处理此问题的帮助将不胜感激。
编辑:如果有帮助,这是我与邮递员一起使用的 http 帖子。
{
"changeTitle": "Test",
"changeType": "Test",
"dateSubmitted": "02/12/2018",
"targetDate": "02/12/2018",
"change_CriticalBankingApps": [
{
"criticalBankingAppId" : 1,
"description" : "Very critical"
},
{
"criticalBankingAppId" : 2,
"description" : "Moderately critical"
}
],
"change_impactedBusinesses": [
{
"ImpactedBusinessId" : 1
},
{
"ImpactedBusinessId" : 2
}
]
}
【问题讨论】:
-
任何答案对您有帮助吗?也许您可以提供一些反馈?
-
非常抱歉,是的,我可以为我的问题添加一些反馈,我是如何解决的,以及这些答案如何帮助我解决问题。
标签: c# sql-server-2012 entity-framework-core asp.net-core-2.0 asp.net-core-webapi