实体框架6.1更新记录的子集

时间:2014-05-09 14:11:07

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

我有一个视图模型,只封装了数据库模型属性的部分。视图模型包含的这些属性是我想要更新的唯一属性。我希望其他属性保留其价值。

在我的研究过程中,我发现this答案似乎对我的需求是完美的,但是,尽管我付出了最大的努力,但我无法让代码按预期工作。

以下是我提出的一个独立的例子:

static void Main() {
    // Person with ID 1 already exists in database.

    // 1. Update the Age and Name.
    Person person = new Person();
    person.Id = 1;
    person.Age = 18;
    person.Name = "Alex";

    // 2. Do not update the NI. I want to preserve that value.
    // person.NINumber = "123456";

    Update(person);
}

static void Update(Person updatedPerson) {
    var context = new PersonContext();

    context.Persons.Attach(updatedPerson);
    var entry = context.Entry(updatedPerson);

    entry.Property(e => e.Name).IsModified = true;
    entry.Property(e => e.Age).IsModified = true;

    // Boom! Throws a validation exception saying that the 
    // NI field is required.
    context.SaveChanges();
}

public class PersonContext : DbContext {
    public DbSet<Person> Persons { get; set; }
}

public class Person {
    public int Id { get; set; }
    [Required]
    public string Name { get; set; }
    [Required] 
    public int Age { get; set; } // this is contrived so, yeah.
    [Required]
    public string NINumber { get; set; }
}

我做错了什么?

3 个答案:

答案 0 :(得分:4)

您的工作基于帖子https://stackoverflow.com/a/15339512/2015959,但在另一个帖子中,未更改的字段(因此不在附加模型中)并非强制性,这就是它起作用的原因。由于您的字段是必填字段,因此您将收到此验证错误。

您的问题可以通过问题Entity Framework validation with partial updates

中提供的解决方案解决

答案 1 :(得分:2)

这是导致它不被保存的验证。您可以使用context.Configuration.ValidateOnSaveEnabled = false;停用验证,它会起作用。要验证特定字段,您可以调用var error = entry.Property(e => e.Name).GetValidationErrors();。所以你当然可以制作一个“更新名称和时间”。仅强制执行业务规则并将这些属性标记为已修改的方法。无需双重查询。

  private static bool UpdateNameAndAge(int id, string name, int age)
  {
     bool success = false;

     var context = new PersonContext();
     context.Configuration.ValidateOnSaveEnabled = false;

     var person = new Person() {Id = id, Name = name, Age = age};
     context.Persons.Attach(person);
     var entry = context.Entry(person);

     // validate the two fields
     var errorsName = entry.Property(e => e.Name).GetValidationErrors();
     var errorsAge = entry.Property(e => e.Age).GetValidationErrors();

     // save if validation was good
     if (!errorsName.Any() && !errorsAge.Any())
     {
        entry.Property(e => e.Name).IsModified = true;
        entry.Property(e => e.Age).IsModified = true;

        if (context.SaveChanges() > 0)
        {
           success = true;
        }
     }

     return success;
  }

答案 2 :(得分:0)

(为清晰起见编辑)

上下文必须具有对象的完整副本才能实施业务规则。只有在附加对象填充了所有必需的属性或者在更新之前将部分视图与完整副本合并之后,才会发生这种情况。

我相信你想要做的事情在概念上是不可能的:做这样的更新需要保留的更改前副本,或者需要对数据库进行两次查询,因为业务层需要对象的完整副本以进行验证。