我一般只是学习EF Core和.NET Core MVC,所以如果之前已经讨论过这个问题我很抱歉 - 我已经搜索过StackOverflow和Microsoft Docs并且什么也没做。
我的模型的简化版本:
public class MyModel
{
public int Id { get; set; }
public int ParentId { get; set; }
public MyModel Parent { get; set; }
public string Type { get; set; }
public string Subtype { get; set; }
}
我的控制器:
public class MyController : Controller
{
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit (int? id )
{
if ( id == null ) return NotFound();
var modelToUpdate = await _context.MyModels
.Include( m => m.Parent )
.FirstOrDefaultAsync( m => m.Id == id );
if ( modelToUpdate == null ) return NotFound();
if ( string.IsNullOrWhitespace(modelToUpdate.Type) )
{
modelToUpdate.Type = modelToUpdate.Parent.Type;
}
if ( await TryUpdateModelAsync<MyModel>(
modelToUpdate,
"",
m => m.Id, m => m.ParentId, m => m.Type, m => m.Subtype
)
) {
try
{
await _context.SaveChangesAsync();
}
catch ( DbUpdateException )
{
ModelState.AddModelError( "", "Unable to save changes" );
}
return RedirectToAction("Index");
}
return View(modelToUpdate);
}
}
将modelToUpdate.Type
设置为modelToUpdate.Parent.Type
未写入数据库。至于为什么我这样做:提高数据集的一致性。我可以用AJAX做客户端,但我不愿意。
EF正在识别实体已更改,但未使用Controller中的最新值更新数据库行。
我查看了_context.ChangeTracker
并尝试手动设置:
_context.Entity(modelToUpdate).State = EntityState.Modified;
和:
_context.Entity(modelToUpdate).Property( m => m.Type ).CurrentValue = modelToUpdate.Type;
和.OriginalValue
,无效。
当我在TryUpdateModelAsync()
语句上设置断点时,modelToUpdate
显示正确的值。 _context.SaveChangesAsync();
处的断点显示为null
。
看起来TryUpdateModelAsync()
正在使用从View返回的原始值,并完全忽略我在后期处理时在Controller中设置的值。
作为一个补充说明:我对[HttpPost("Create")]
有类似的逻辑,并且完美无缺 - 但我在那里使用了以下内容:
if ( ModelState.IsValid )
{
_context.Add(model);
await _context.SaveChangesAsync();
}
有人可以解释我在这里缺少关于状态跟踪的内容吗?