Подтвердить что ты не робот

Как обновлять не все поля объекта с использованием Entity Framework и EntityState.Modified

Мне нужно обновить все поля, кроме property1 и property2 для данного объекта сущности.
Имея этот код:

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

                context.SaveChanges();               
         }
        return View(obj);
    }

Как изменить его, чтобы добавить исключение в obj.property1 и obj.property2 для того, чтобы не обновляться этим кодом?

4b9b3361

Ответ 1

Предположим, что у вас есть набор исключаемых свойств:

var excluded = new[] { "property1", "property2" };

С EF5 на .NET 4.5 вы можете сделать это:

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

Это использует новую функцию EF5 на .NET 4.5, которая позволяет устанавливать свойство как не измененное даже после того, как оно было ранее установлено для изменения.

При использовании EF 4.3.1 или EF5 на .NET 4 вы можете сделать это вместо:

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

Ответ 2

Вы не можете определить такое исключение. Однако вы можете отметить отдельные свойства как измененные:

context.Entry(obj).Property(o => o.Property3).IsModified = true;
context.Entry(obj).Property(o => o.Property4).IsModified = true;
// etc.

Обратите внимание, что установка IsModified на false не поддерживается после того, как вы отметили состояние всей сущности на 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();

Ответ 3

Этот вопрос уже хорошо ответил, но я хотел бы предоставить метод расширения для тех, кто хотел бы использовать его.

Этот код был разработан для 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 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();
}

Пример использования

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

    //For argument 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
}

Ответ 4

В ответах выше (большинство из них) используется DbContext. Для тех, кто использует ObjectContext, эти решения недоступны.

Вот решение для ObjectContext строго (EF5.NET 4.5):

ctx.AddObject("ENTITYNAME", item);
ctx.ObjectStateManager.ChangeObjectState(item, EntityState.Modified);

var entry = ctx.ObjectStateManager.GetObjectStateEntry(item);
entry.RejectPropertyChanges("PROPERTY_TO_EXCLUDE");