【问题标题】:stoping ef-core to insert referenced record in to master table停止 ef-core 将引用的记录插入到主表中
【发布时间】:2019-10-28 15:51:10
【问题描述】:

我有如下设置。

  1. Supermaster 拥有 Master 的集合。
  2. Master 具有对 Reference PK Id 的 FK 引用
  3. Reference 表具有只读引用数据。

在 ef 代码中,当我从 Supermaster 表加载记录时,我根据某些条件将 reference 添加到每个 Master

在提交Supermaster 时,我希望Supermaster 与所有Master 参考Reference 一起保存。

但在dbContext.SaveChanges() 上,EF 尝试将记录插入Reference,但由于 PK 约束而失败。

我到目前为止所尝试的

我尝试使用 Fluent API 与外键创建一对一关系。

我在保存上下文之前尝试过分离实体

_context.Entry(programmingRecord.ProgrammingRecordParameters.Select(x=>x.ValidationRule)).State = EntityState.Detached;

.

这是代码。

实体

Public class Supermaster
{
    public virtual ICollection<Master> ProgrammingRecordParameters { get; set; }
}

   public class Reference
    {
        public int Id { get; set; }
        public string Description { get; set; }
    }


   public class Master
    {
        public int Id { get; set; }
        public string DataGroup { get; set; }
        [ForeignKey("ValidationRuleId")]
        public Reference ValidationRule { get; set; }
        public int? ValidationRuleId { get; set; }
    }

API

    private void AddParameter(
            Supermaster rec,
            Master programmableParameter)
        {
            var param = new Master
            {                
                DataGroup = programmableParameter.DataGroup,
                ValidationRule = _context.References.FirstOrDefault(x=>x.Description==programmableParameter.DataGroup
            };

            rec.ProgrammingRecordParameters.Add(param);
        }

        public IActionResult PostProgrammingRecord([FromBody] Master programmingRecord)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }


            var repo = new ProgrammingRepository(_context);
            _context.ProgrammingRecords.Add(programmingRecord);
                _context.SaveChanges();
       }     

下面是错误堆栈

  HResult=0x80131500
  Message=An error occurred while updating the entries. See the inner exception for details.
  Source=Microsoft.EntityFrameworkCore.Relational
  StackTrace:
   at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(DbContext _, ValueTuple`2 parameters)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(IEnumerable`1 commandBatches, IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Storage.RelationalDatabase.SaveChanges(IReadOnlyList`1 entries)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IReadOnlyList`1 entriesToSave)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
   at RadioTMS.Web.Controllers.API.ProgrammingController.PostProgrammingRecord(ProgrammingRecord programmingRecord) in D:\TMS_Git_Repo\radio-tms\RadioTMS.Web\Controllers\API\ProgrammingController.cs:line 181
   at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
   at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()

Inner Exception 1:
SqlException: Cannot insert explicit value for identity column in table 'ValidationRules' when IDENTITY_INSERT is set to OFF.

【问题讨论】:

  • context.Entry(param.ValidationRule).Staterec.ProgrammingRecordParameters.Add(param); 之前和之后返回什么?
  • @Minijack - 相当于Unchanged
  • @SKDesai 您的AddParameter(programmableParameter) 方法会在内部创建一个新的param,并且不会更改原始programmableParameter。因此,当您稍后调用_context.ProgrammingRecords.Add(programmingRecord); 时,您将在programmingRecord 而不是param 上进行操作。因为programmingRecord.ValidationRule没有被跟踪,EF-Core会尝试插入/更新数据库,导致异常。
  • @itminus - 啊……我认为是这样。我认为在这种情况下,我需要明确告诉 EF 在保存 DBContext 之前不要更新验证规则。让我试一试,我会更新...

标签: c# asp.net-core ef-code-first entity-framework-core ef-core-2.1


【解决方案1】:

EF 正在尝试在引用表中插入记录,因为实体上下文没有加载引用数据。您应该在调用保存更改之前在上下文中加载引用记录。

【讨论】:

  • DBContext 填充了参考数据。我可以确认,因为我在AddParameter() 通话中使用这些数据。
猜你喜欢
  • 2020-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-26
相关资源
最近更新 更多