更新验证失败后,使用.Include(相关实体)重新显示原始模型

时间:2018-02-22 06:30:26

标签: c# asp.net-core entity-framework-core

当用户发送GET请求来编辑记录时,我正在加载使用.Include()发送到相关实体的视图的模型,如下所示:

 var client = await _context.Client
                             .Include(c => c.Office)
                             .Where(c => c.client_id == id)
                             .AsNoTracking()
                             .SingleOrDefaultAsync();
 return View(client);

当用户POST回编辑表单并且缺少必需字段ModelState.IsValid == false时,不会执行任何更新,并且将未保存更改的模型发送回视图。

public async Task<IActionResult> Edit(Client client_edited )
{
    if (!ModelState.IsValid)
    {
            return View(client_edited); // .Include(c => c.Office) is missing
    }
}

如何返回发布的视图模型(包含用户待定更改)并重新附加所需的.Include()?

当我重新查询模型(客户端)记录时,挂起的更改将丢失。

我正在尝试做一些事情,比如重新查询包含的客户端,然后通过顶部的待定更改复制客户端。有点像...

var client = await _context.Client
                             .Include(c => c.Office)
                             .Where(c => c.client_id == id)
                             .AsNoTracking()
                             .SingleOrDefaultAsync();

 // need to copy pending client_edited changes to the client 
 // but does not work because it overwrites the .Include(c => c.Office)
 client = client_edited 

 return View(client_edited);

1 个答案:

答案 0 :(得分:0)

回答我自己的问题以防其他人......

基于blog post by Lori Peterson Entity Framework cloning,参见 EF复制当前值 ,我能够通过几行代码解决问题,例如:

public async Task<IActionResult> Edit(Client client_posted)
{
  if (!ModelState.IsValid)
  {

    ModelState.AddModelError("", "Record is missing required values");

    // requery the client entity from our db to get related child entities
    var client_current = await _context.Client
                                        .Include(c => c.Office)
                                        // include 4 or 5 more entities here
                                        .Where(c => c.client_id == client_posted.client_id)
                                        .AsNoTracking()
                                        .SingleOrDefaultAsync();

    // now replace client_current values with client_posted values by

    // 1 - add entity to your db context (we are not saving it)
    _myDbContext.Client.Add(client_posted);

    // 2 - use the db context to extract current values from the client entity posted
    var client_posted_values =_myDbContext.Entry(client_posted).CurrentValues;

    // 3 - copy the extracted values to the client_current we re-queried from db
    _myDbContext.Entry(client_current).CurrentValues.SetValues(client_posted_values);

    // 4 return the view passing client with original values and the attached office entity(ies)
    return View(client_current);
  }
  // otherwise ModelState is valid, do the update here
  ...
  ...
}