如何忽略实体框架核心中SaveChanges的特定字段



比方说,我有一个具有以下属性的模型Car(为了简单起见,我跳过了get/set(:

string Name;    // user can change
string Secret;  // user cannot change
DateTime CreatedAt = DateTime.Now;  // even we cannot change

然后在ASP Web应用程序3.1中,脚手架生成具有以下内容的Edit.cshtml.cs(简化(:

[BindProperty]
public Car Car { get; set; }
public Task<IActionResult> OnPost()
{
_context.Attach(LanguageExporter).State = EntityState.Modified;
_context.SaveChanges();
// redirect ...
}

因此,它允许用户使用Car的所有字段进行POST。

但实际上,我想完全忽略CreatedAt,不允许从POST参数更改Secret(但允许从代码更改(。[BindNever]没有帮助,因为ASP跳过了Secret,它保留了default(string) => null,这是我不想要的。对于CreatedAt,它保持default(DateTime) => 01.01.0001


因此,我向社区提出了一个问题,即如何自动化编辑模型的过程?

在我看来,ASP应该忽略一些POST参数,EF应该忽略更新一些属性。或者ASP应该先获取模型,然后只更改特定的属性(例如,保留CreatedAt(。

在这种情况下,最佳实践是什么?

如果您想在编辑时忽略CreatedAt,可以将其IsModified属性设置为false,如下所示:

_context.Attach(Car).State = EntityState.Modified;
_context.Entry<Car>(Car).Property(x => x.CreatedAt).IsModified = false;

创建API时,应该使用ViewModel,它不是数据库实体,而是请求所需属性的表示。

例如,如果允许用户编辑用户名和电话号码,则视图模型将只包含这两个属性(即使"用户"数据库实体可能包含更多属性(。然后,您会找到要更新的数据库记录,只更改需要更改的属性,然后保存更改。

class EditViewModel
{ 
public int Id {get;set;}
public string Name {get;set;}
public string PhoneNumber {get;set;}
}
[BindProperty]
public EditViewModel ViewModel {get;set;}
public void OnPost()
{
var entity = _context.Single(x=>x.Id == ViewModel.Id);
entity.Name = ViewModel.Name;
entity.PhoneNumber = ViewModel.PhoneNumber;
_context.SaveChanges();
}

}

最新更新