如何使用Entity Framework和EntityState.Modified更新对象的每个字段

mhm*_*hmd 35 entity-framework entity-framework-4.1

我需要为给定的实体对象更新除property1和property2之外的所有字段.
有这个代码:

    [HttpPost]
    public ActionResult Add(object obj)
    {
        if (ModelState.IsValid)
        {
                context.Entry(obj).State = System.Data.EntityState.Modified;

                context.SaveChanges();               
         }
        return View(obj);
    }
Run Code Online (Sandbox Code Playgroud)

如何更改它以向obj.property1和obj.property2添加例外,以便不使用此代码进行更新?

Art*_*ers 67

假设您有一组要排除的属性:

var excluded = new[] { "property1", "property2" };
Run Code Online (Sandbox Code Playgroud)

使用.NET 4.5上的EF5,您可以这样做:

var entry = context.Entry(obj);
entry.State = EntityState.Modified;
foreach (var name in excluded)
{
    entry.Property(name).IsModified = false;
}
Run Code Online (Sandbox Code Playgroud)

这在.NET 4.5上使用了EF5的一项新功能,即使以前将属性设置为已修改,也可以将属性设置为未修改.

在.NET 4上使用EF 4.3.1或EF5时,您可以这样做:

var entry = context.Entry(obj);
foreach (var name in entry.CurrentValues.PropertyNames.Except(excluded))
{
    entry.Property(name).IsModified = true;
}
Run Code Online (Sandbox Code Playgroud)

  • 好的!也适用于 EF core 2.2.4 (2认同)

Sla*_*uma 21

您无法定义此类异常.但是,您可以将单个属性标记为已修改:

context.Entry(obj).Property(o => o.Property3).IsModified = true;
context.Entry(obj).Property(o => o.Property4).IsModified = true;
// etc.
Run Code Online (Sandbox Code Playgroud)

需要注意的是设置IsModifiedfalse一旦您已标记了整个实体的状态不支持Modified.

出于您的目的,我实际上更愿意从数据库加载实体,然后使用常规更改跟踪更新它:

var objInDB = context.Objects.Single(o => o.Id == obj.Id);

obj.Property1 = objInDB.Property1;
obj.Property2 = objInDB.Property2;

context.Entry(objInDB).CurrentValues.SetValues(obj);

context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)


dys*_*oko 9

这个问题已经很好地回答了,但我想为任何想要使用它的人提供一种扩展方法.

此代码是为EF 4.3.1开发的

//You will need to import/use these namespaces    
using System.Data.Entity;
using System.Data.Entity.Infrastructure;    

//Update an entity object's specified columns, comma separated
//This method assumes you already have a context open/initialized
public static void Update<T>(this DbContext context, T entityObject, params string[] properties) where T : class
{
    context.Set<T>().Attach(entityObject);

    var entry = context.Entry(entityObject);

    foreach(string name in properties)
        entry.Property(name).IsModified = true;

    context.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)

用法示例

using (FooEntities context = new FooEntities())
{
    FooEntity ef = new FooEntity();

    //For argument's sake say this entity has 4 columns: 
    //    FooID (PK), BarID (FK), Name, Age, CreatedBy, CreatedOn

    //Mock changes
    ef.FooID = 1;
    ef.Name = "Billy";
    ef.Age = 85;

    context.Update<FooEntity>(ef, "Name", "Age"); //I only want to update Name and Age
}
Run Code Online (Sandbox Code Playgroud)