在EF核心中执行部分更新并且永不更新某些属性的最佳方法是什么?

时间:2018-04-19 13:24:57

标签: c# entity-framework entity-framework-core

我知道您可以执行var myObj = _db.MyTable.FirstOrDefault(x=>x.Id==id)之类的操作,然后根据要更新的属性更新myObj属性,但有更好的方法可以更新{{1的10个属性中的6个属性并留下另外4个或者将它们标记为只设置一次并且永远不能从ef核心更新的方式?

myObj

显然你可以写一些像 public class MyObject { public string Id { get; set; } public string Prop1 { get; set; } public string Prop2 { get; set; } public string Prop3 { get; set; } public string Prop4 { get; set; } public string Prop5 { get; set; } public string Prop6 { get; set; } public string Prop7 { get; set; } public string Prop8 { get; set; } public string Prop9 { get; set; } } public void UpdateObj(MyObject ojToUpdate) { //Is there a better way to write this function if you only want to update a set amount of properties var myObj = _db.MyObject.First(x=>x.Id==ojToUpdate.Id); myObj.Prop1 = objToUpdate.Prop1; myObj.Prop2 = objToUpdate.Prop2; myObj.Prop3 = objToUpdate.Prop3; myObj.Prop4 = objToUpdate.Prop4; myObj.Prop5 = objToUpdate.Prop5; myObj.Prop6 = objToUpdate.Prop6; _db.SaveChanges(); } 这样的东西。这个陈述的问题是用户可以更新道具4/5/6,我不希望他们更新。 是的我知道你可以写_db.MyObject.Update(objToUpdate)然后调用保存更改,但这会超过我希望生成一次但永远不会再次修改的属性。

提前致谢。

4 个答案:

答案 0 :(得分:9)

从EF Core 2.0开始,您可以使用IProperty.AfterSaveBehavior属性:

  

获取一个值,该值指示在将实体保存到数据库后是否可以修改此属性。

     

如果Throw,则在实体存在于数据库中之后为此属性分配新值时,将抛出异常。

     

如果Ignore,则将忽略对数据库中已存在的实体的属性值的任何修改。

您需要的是Ignore选项。在撰写本文时,没有专门的流畅API方法,但Setting an explicit value during update包含了如何做到这一点的示例。

举个例子,像这样:

modelBuilder.Entity<MyObject>(builder =>
{
    builder.Property(e => e.Prop7).Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore;
    builder.Property(e => e.Prop8).Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore;
    builder.Property(e => e.Prop9).Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore;
});

现在两个

public void UpdateObj(MyObject objToUpdate)
{
    var myObj = _db.MyObject.First(x => x.Id == objToUpdate.Id);
    _db.Entry(myObj).CurrentValues.SetValues(myObjToUpdate);
    _db.SaveChanges();
}

public void UpdateObj(MyObject objToUpdate)
{
    _db.Update(myObjToUpdate);
    _db.SaveChanges();
}

将忽略已传递的Prop7的{​​{1}},Prop8Prop9值。

答案 1 :(得分:2)

如果您有实体:

field WebDriver

你跑:

public class Person
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public string Address { get; set; }
}

EF 将生成以下SQL语句:

enter image description here

您可以使用 SQL Server Profiler 进行验证,如果您更新6/10属性也是如此。

答案 2 :(得分:0)

您还可以在dbContext的OnModelCreating内部使用之前提到的AfterSaveBehavior,如下所示:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{

modelBuilder.Entity<someobject>(builder =>
{
    builder.Property(i => i.CreatedAt).Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore;
});

现在,“ someobject”上的“ CreatedAt”属性将被第一次保存,然后在以后的更新中永远不会被修改。

答案 3 :(得分:0)

从3.1开始,可以通过使用SetAfterSaveBehavior()扩展方法来实现:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<someobject>(builder =>
{
    builder.Property(i => i.CreatedAt).Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Ignore);
});

https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.mutablepropertyextensions.setaftersavebehavior?view=efcore-3.1