EF Core - 当实体应该是外键关系时,为什么实体被另存为新的数据库实体?



远离上下文的 EF6 DB 优先模型 - 我正在构建一个对数据库上下文使用 EF Core Code First 模型的 ASP Core API。若要在滚动更新中执行此操作,我的上下文必须与当前数据库架构一起存在,因此我使用 EF Fluent API 为不反映当前数据库架构的代码优先模型生成实体映射。

我在插入操作期间遇到实体上的导航属性问题。使用标准 .包含(x => x.OtherEntity) 格式,将主实体保存回数据库是问题所在。

使用 Fluent API 映射实体对我来说是新的,因此学习曲线可能是我的问题所在。我尝试使用 OwnsOne 与 HasOne,但 MS 文档表明 HasOne() 是进行此映射的正确方法。

我的主要实体有外键字段的影子属性,当我使用 .HasOne() 在流畅映射中(在下面的代码中)

在这种情况下,异常消息没有用,因为它们不反映映射问题,它们建议当导航属性的表具有标识列时无法插入数据(即无法插入具有显式 ID 的记录)-> 这很奇怪,因为我没有尝试通过这些导航属性插入数据,我只是尝试使用外键将我的主实体链接到该辅助实体。

实体映射:

// WorkOrder Entity Mapping:
modelBuilder.Entity<WorkOrder>().ToTable("WorkOrder");
modelBuilder.Entity<WorkOrder>().Property(x => x.Id).HasColumnName("IDWorkOrder");
modelBuilder.Entity<WorkOrder>().Property(x => x.CreatedBy).HasColumnName("IDUserCreated");
modelBuilder.Entity<WorkOrder>().Property(x => x.UpdatedBy).HasColumnName("IDUserUpdated");
modelBuilder.Entity<WorkOrder>().Property<int?>("IDWOCategory");
modelBuilder.Entity<WorkOrder>().Property<int?>("IDProblem");
modelBuilder.Entity<WorkOrder>().Property<int?>("IDWOCostCenter");
modelBuilder.Entity<WorkOrder>().Property<int?>("IDWOLocation");
modelBuilder.Entity<WorkOrder>().Property<int?>("IDWOPriority");
modelBuilder.Entity<WorkOrder>().Property<int?>("IDWOStatus");
modelBuilder.Entity<WorkOrder>().Property<int?>("IDWOTrade");
modelBuilder.Entity<WorkOrder>().Property<Guid?>("IDUserCompleted");
modelBuilder.Entity<WorkOrder>().Property<Guid?>("IDParentWO");
// WO Navigation Properties:
modelBuilder.Entity<WorkOrder>().HasOne(x => x.Category).WithOne().HasForeignKey<WorkOrder>("IDWOCategory").HasPrincipalKey<Category>(c => c.Id);
modelBuilder.Entity<WorkOrder>().HasOne(x => x.Problem).WithOne().HasForeignKey<WorkOrder>("IDProblem").HasPrincipalKey<Problem>(c => c.Id);
modelBuilder.Entity<WorkOrder>().HasOne(x => x.CostCenter).WithOne().HasForeignKey<WorkOrder>("IDWOCostCenter").HasPrincipalKey<CostCenter>(c => c.Id);
modelBuilder.Entity<WorkOrder>().HasOne(x => x.Location).WithOne().HasForeignKey<WorkOrder>("IDWOLocation").HasPrincipalKey<Location>(c => c.Id);
modelBuilder.Entity<WorkOrder>().HasOne(x => x.Priority).WithOne().HasForeignKey<WorkOrder>("IDWOPriority").HasPrincipalKey<Priority>(c => c.Id);
modelBuilder.Entity<WorkOrder>().HasOne(x => x.Status).WithOne().HasForeignKey<WorkOrder>("IDWOStatus").HasPrincipalKey<Status>(c => c.Id);
modelBuilder.Entity<WorkOrder>().HasOne(x => x.Trade).WithOne().HasForeignKey<WorkOrder>("IDWOTrade").HasPrincipalKey<Trade>(c => c.Id);
modelBuilder.Entity<WorkOrder>().HasOne(x => x.Requester).WithOne().HasForeignKey<WorkOrder>("IDRequester").HasPrincipalKey<Requester>(c => c.Id);
modelBuilder.Entity<WorkOrder>().HasOne(x => x.UserCompleted).WithOne().HasForeignKey<WorkOrder>("IDUserCompleted").HasPrincipalKey<User>(c => c.Id);
modelBuilder.Entity<WorkOrder>().HasOne(x => x.ParentWorkOrder).WithOne().HasForeignKey<WorkOrder>("IDParentWO").HasPrincipalKey<WorkOrder>(c => c.Id);

在控制器中获取数据:(就像一个魅力!

[HttpGet("{Id}")]
public async Task<ActionResult<List<WorkOrder>>> GetWorkOrders(Guid Id)
{
var result = await WorkOrdersContext.WorkOrders
.Include(x => x.Problem)
.Include(x => x.Status)
.Include(x => x.Requester)
.Include(x => x.ParentWorkOrder)
.Include(x => x.Category)
.Include(x => x.Trade)
.Include(x => x.Location)
.Include(x => x.CostCenter)
.Include(x => x.Priority)
.Where(x => x.Id == Id)
.ToListAsync();
return Ok(result);
}

在控制器中保存新数据:(它在哪里崩溃!

[HttpPost]
public async Task<ActionResult<WorkOrder>> CreateWorkOrderFromPending([FromBody]WorkOrder call)
{
// Insert the Work Order to the DB:
DbContext.WorkOrders.Add(call);
var saveResult = await DbContext.SaveChangesAsync();
// Check if any oddities occurred during the save:
if (saveResult == 0) return BadRequest("An Error occurred during saving and the Call was not saved, please try again.");
// Return the Inserted Work Order:
return Ok(call);
}

在这里,当它尝试保存新的工作订单时,它会引发异常,因为映射的类型(问题、类别、成本中心等来自实体映射代码片段)它试图将数据另存为新实体,而不是在现有实体上构建 FK 关系。我认为这就是我缺少流畅 API 的一些逻辑的地方!

任何帮助将不胜感激,因为很难将这个问题用几句话用于谷歌搜索!

感谢 @DavidBrowne-Microsoft,我有了答案,试图让我们过去的 DB First 东西与 .NET Core 共存并非易事,并且来自代码优先背景,其中.Add() 是有效的路径,很难看出如何.Attach() 打算做这个伎俩。

[HttpPost]
public async Task<ActionResult<WorkOrder>> CreateWorkOrderFromPending([FromBody]WorkOrder call)
{
// Insert the Work Order to the DB:
// DbContext.WorkOrders.Add(call);
var entity = DbContext.WorkOrders.Attach(call);
entity.State = EntityState.Added;
var saveResult = await DbContext.SaveChangesAsync();
// Check if any oddities occurred during the save:
if (saveResult == 0) return BadRequest("An Error occurred during saving and the Call was not saved, please try again.");
// Return the Inserted Work Order:
return Ok(call);
}

用。Attach() 代替 .Add() 做到了诀窍,将实体放入并从我的 Fluent 映射中将 FK 映射到它们各自的阴影属性!

相关内容

  • 没有找到相关文章

最新更新