实体框架核心:如何使用嵌套字段更新记录?

时间:2019-11-30 22:35:38

标签: entity-framework .net-core

我有一个使用MSVS 2019的简单的“ ContactsList” ASP.Net Core Web(REST)应用程序,.Net Core 3.0,MSSQL LocalDB。

我的“联系人”实体包含“注释”列表。

当我创建一个已经包含一个或多个便笺的新联系人时,一切正常。 EF将注释自动插入注释表中。

但是当我尝试更新一个联系人时,EF似乎无视“注释”。

问:对于“更新”,我是否需要在控制器中编写代码以自己明确更新笔记?    还是我在做“错误”的事情,以至于EF无法“自动”进行应有的更新?

  • Models / Contact.cs:

    public class Contact
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int ContactId { get; set; }
        public string Name { get; set; }
        public string EMail { get; set; }
        public string Phone1 { get; set; }
        public string Phone2 { get; set; }
        public string Address1 { get; set; }
        public string Address2 { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string Zip { get; set; }
        public List<Note> Notes { get; set; }
    }
    
  • Models / Note.cs:

    public class Note
    {
        public Note()
        {
            this.Date = DateTime.Now; // Default value: local "now"
        }
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int NoteId { get; set; }
        public string Text { get; set; }
        public DateTime Date { get; set; }
        [ForeignKey("Contact")]
        public int ContactId { get; set; }
    }
    
  • Controllers / ContactsController.cs(POST的工作原理:如果联系人列表中有注释,则将其添加):

    [HttpPost]
    public async Task<ActionResult<Contact>> PostContact(Contact contact)
    {
        _context.Contacts.Add(contact);
        await _context.SaveChangesAsync();
    
        //return CreatedAtAction("GetContact", new { id = contact.ContactId }, contact);
        return CreatedAtAction(nameof(GetContact), new { id = contact.ContactId }, contact);
    }
    
  • Controllers / ContactsController.cs(PUT似乎完全忽略了任何相关注释):

    [HttpPut("{id}")]
    public async Task<IActionResult> PutContact(int id, Contact contact)
    {
        if (id != contact.ContactId)
        {
            return BadRequest();
        }
    
        _context.Entry(contact).State = EntityState.Modified;
    
        try
        {
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!ContactExists(id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
    
        return NoContent();
    }
    

用于POST的SQL显示四个单独的INSERT:一个用于联系人,一个用于每个便笺。

用于PUT的SQL仅显示一个UPDATE:仅联系人;没什么。

调试器显示“注释”显然是PutContact()控制器收到的“联系人”记录的一部分。

问:EF应该自动处理“更新”笔记吗,还是需要在控制器中手动编码更新?

1 个答案:

答案 0 :(得分:1)

  

实体框架核心会忽略关系,除非您在查询中明确包含它们。

_context.Entry(contact).State = EntityState.Modified;

上面一行的问题是,您没有指定相关数据已被修改,因此在查询中将忽略该数据。

所以你可以

  • 附加所有相关数据
  • 将相关数据的状态设置为EntityState.Modified

或者您可以

  • 查询数据库中的对象并包含相关数据
  • 然后将联系人对象分配给该查询对象
 var dbContactObj = _context.Contacts.Include(x => x.Notes).First(x => x.Id == contact.Id);
 dbContactObj = contact;

 _context.SaveChangesAsync();