2012-02-13 18 views
1

少しデモを行うための非常に単純なMVC3アプリケーションを作成しましたが、問題に対して実行しています。エンティティを私の視点に戻して編集してからポストしますが、このプロセスではエンティティのチェンジトラッキング機能が失われます。エンティティを私の視点に戻すと、エンティティ・フレームワーク・プロキシ・クラスになりますが、私の視点から戻ってくると、それは「Person」クラス(エンティティは「人」と呼ばれます)です。MVC3で編集するとエンティティのチェンジトラッキングが失われる

は、ここに私のリポジトリクラスです:

public class PersonRepository : IPersonRepository 
{ 
    public EfContext Uow { get; set; } 

    public PersonRepository(IUnitOfWork uow) 
    { 
     Uow = uow as EfContext; 
    } 

    // yada yada yada 

    public void Add(Person person) 
    { 
     Uow.Persons.Add(person); 
    } 
} 

このエンティティはHtml.EditorForModelで作成した簡単なフォームを、持っている私の見解に送信されます。その後、私はこれをこの方法に戻します:

[HttpPost] 
public ActionResult Edit(Person person) 
{ 
    if (ModelState.IsValid) 
    { 
     _personRepository.Add(person); 
     _personRepository.Uow.Commit(); 

     return RedirectToAction("Index"); 
    } 

    return View(person); 
} 

そして、それはもはや追跡されたプロキシクラスではありません。エンティティ・フレームワークは新しいオブジェクトとしてオブジェクトを追加しようとしているため、エンティティ・フレームワークに変更を検出し、代わりに更新文を作成させたいので、これは主キー違反となります。ただのSaveChangesを(呼び出した上でああ方法により、)コードにCommitメソッドを、ここではクラスがあります:ところで

public class EfContext : DbContext, IUnitOfWork 
{ 
    public DbSet<Account> Accounts { get; set; } 
    public DbSet<Person> Persons { get; set; } 

    public void Commit() 
    { 
     SaveChanges(); 
    } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); 
    } 
} 

、これは私のエンティティクラスである:

public class Person 
{ 
    [HiddenInput(DisplayValue = false)] 
    public Guid Id { get; set; } 

    public string FirstName { get; set; } 

    public string LastName { get; set; } 

    public virtual ICollection<Account> Accounts { get; set; } 
} 

誰がどのように知っていますこれを修正するには?私はこれまで私が覚えている限り働いていた、私はちょうど方法を知らない。

ありがとうございます!

答えて

1

リポジトリにUpdateメソッドを定義して、エンティティを添付し、変更されたものとしてマークします。

public class PersonRepository : IPersonRepository 
{ 
    // yada yada yada 

    public void Add(Person person) 
    { 
     Uow.Persons.Add(person); 
    } 

    public void Update(Person person) 
    { 
     Uow.Persons.Attach(person); 
     Uow.Entry(person).State = EntityState.Modified; 
    } 
} 

[HttpPost] 
public ActionResult Edit(Person person) 
{ 
    if (ModelState.IsValid) 
    { 
     _personRepository.Update(person); 
     _personRepository.Uow.Commit(); 

     return RedirectToAction("Index"); 
    } 

    return View(person); 
} 
+0

それはうまくいくようなサウンドです。しかし、それは「悪い」ではない?明示的に状態を設定するにはちょっと汚れているようです。 –

+1

@Avalaxyいいえこれは、EFがエンティティの状態を認識していないため、エンティティをアタッチするときのプロセスの一部です。リポジトリは、実装の詳細を知っている必要があります。 – Eranga

2

私はあなたが(コンストラクタでたりのIoCフレームワークか何かで、依存関係として渡された)要求ごとにリポジトリを作成していることを前提としています。その場合、コントローラメソッドで受け取ったエンティティは、別の要求で作成されたため実際には追跡されません。あなたはそれを文脈に「添付」して修正してマークしなければならないので、EFはそれが変更されたことを知り、それをDBに保存する必要があります。

+0

ええ、リポジトリはDIコンテナによって私のコントローラに注入されます。あなたの答えをありがとう、それはおそらく解決策です。 –

0

ここでは3番目の解決法があります。

id整数を受け取るようにMVCアクションを設定できます。その整数を使用して、データベースからエンティティを取得します。次に、コントローラのUpdateModelメソッドを呼び出します。これにより、新しいフォームの値が既存のオブジェクトにバインドされますが、変更されていないプロパティやフォームにないプロパティが変更されることはありません。

関連する問題