EF-Core 尝试插入已存在的关系数据

tom*_*zzi 5 c# entity-framework asp.net-core

我正在尝试使用 EF-Core 将一个引用其他对象的对象添加到我的数据库中。这是我的两个模型:

    public class Contact : Entity
    {
        #nullable enable
        public string? Name1 { get; set; }
        public string? Name2 { get; set; }
        public Company? Company { get; set; }
        public string? Salutation { get; set; }
        public string? Title { get; set; }
        public DateTime? Birthday { get; set; }
        public string? Address { get; set; }
        public string? Postcode { get; set; }
        public string? City { get; set; }
        public string? Country { get; set; }
        public string? Mail { get; set; }
        public string? MailSecond { get; set; }
        public string? PhoneFixed { get; set; }
        public string? PhoneFixedSecond { get; set; }
        public string? PhoneMobile { get; set; }
        public string? Fax { get; set; }
        public string? Url { get; set; }
        public string? SkypeName { get; set; }
        public bool? IsLead { get; set; }
        public string? Remarks { get; set; }
    }

    public class Company : Entity
    {
        #nullable enable
        public string? Name { get; set; }
        public List<Contact>? Contacts { get; set; }
        public string? Address { get; set; }
        public string? Postcode { get; set; }
        public string? City { get; set; }
        public string? Country { get; set; }
        public string? Url { get; set; }
        public string? Remarks { get; set; }
        public string? UpdatedAt { get; set; }
    }

    public class Entity
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        public DateTime? CreatedAt { get; set; }
        public DateTime? LastEdited { get; set; }
        public string? BexioId { get; set; }
    }

Run Code Online (Sandbox Code Playgroud)

这是我的 DbContext:

    public class DatabaseContext : DbContext
    {
        public DatabaseContext(DbContextOptions<DatabaseContext> options)
            : base(options)
        {
        }
        public DbSet<Company> Companies { get; set; }
        public DbSet<Contact> Contacts { get; set; }
        
        protected override void OnModelCreating(ModelBuilder modelbuilder)
        {
            modelbuilder.Entity<Contact>().ToTable("Contacts"):
            modelbuilder.Entity<Company>().ToTable("Companies");
        }
    }

Run Code Online (Sandbox Code Playgroud)

当尝试使用以下代码插入数据时,出现以下错误:

        public object Add(string values)
        {
            var newContact = new Models.Contact();
            JsonConvert.PopulateObject(values, newContact);

            if (!TryValidateModel(newContact))
                return BadRequest(ModelState);

            _context.Contacts.Add(newContact);
            _context.SaveChanges();

            return Ok();
        }
Run Code Online (Sandbox Code Playgroud)
Microsoft.EntityFrameworkCore.DbUpdateException
  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(IEnumerable`1 commandBatches, IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Storage.RelationalDatabase.SaveChanges(IList`1 entries)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IList`1 entriesToSave)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(DbContext _, Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
   at microtom.portal.Controllers.ContactController.Add(String values) in C:\Users\tpeduzzi\Documents\microtom\microtom.portal\Controllers\ContactController.cs:line 38
   at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<<InvokeActionMethodAsync>g__Logged|12_1>d.MoveNext()

  This exception was originally thrown at this call stack:
    [External Code]

Inner Exception 1:
SqlException: Cannot insert explicit value for identity column in table 'Companies' when IDENTITY_INSERT is set to OFF.
Run Code Online (Sandbox Code Playgroud)

我不太清楚发生了什么事。我认为问题在于 EF-Core 试图将对象插入联系人对象的 Company 字段中,即使数据已经在数据库中并且该公司的 Id 字段已由数据库填写。谁能告诉我我做错了什么?几天来我一直在尝试解决这个问题,但我非常绝望......我正在按照网上和亲自告诉我的方式去做。提前致谢!

Gur*_*ron 4

_context.Attach(newContact.Company)之前打电话_context.Add

EF 使用跟踪的概念来查看更改并将其传播到数据库。在您中,当前代码newContact.Company不为空,并且它作为对象图的一部分添加到当前上下文newContact。由于上下文对此一无所知,因此Company它会将其视为新的并尝试将其保存到数据库中。DbContext.Attach默认情况下,开始使用状态跟踪给定实体和可从给定实体访问的条目Unchanged,因此它将认为它是现有的(且未更改的)实体,并且不会尝试将其保存到数据库。