web-dev-qa-db-ja.com

Entity Framework6.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; }
}

私は何が間違っているのですか?

16
Caster Troy

あなたは投稿に基づいて作業を行いました https://stackoverflow.com/a/15339512/2015959 しかし、他のスレッドでは、変更されなかった(したがって、添付されたフィールドにはありませんでした)モデル)は必須ではありませんでした、そしてそれがそれが働いた理由です。フィールドは必須であるため、この検証エラーが発生します。

あなたの問題は、質問で提供された解決策によって解決することができます 部分的な更新を伴うエンティティフレームワークの検証

4
Radu Pascal

保存されない原因となっているのは検証です。 _context.Configuration.ValidateOnSaveEnabled = false;_を使用して検証を無効にすると、機能します。特定のフィールドを検証するには、var error = entry.Property(e => e.Name).GetValidationErrors();を呼び出すことができます。したがって、ビジネスルールのみを適用し、それらのプロパティに変更済みのフラグを付けるだけの「UpdateNameAndAge」メソッドを作成できます。二重クエリは必要ありません。

_  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;
  }
_
3
jltrem

(わかりやすくするために編集)

ビジネスルールを適用するには、コンテキストにオブジェクトの完全なコピーが必要です。これは、アタッチされたオブジェクトに必要なすべてのプロパティが入力されているか、更新前に部分ビューが完全なコピーとマージされている場合にのみ発生する可能性があります。

あなたがやりたいことは概念的に不可能だと思います。このような更新を行うには、保存された変更前のコピー、または検証のためにビジネス層がオブジェクトの完全なコピーを必要とするため、データベースへの2つのクエリが必要になります。

0
esmoore68