2013-03-26 64 views
12

EntityFramework 5を使用してオブジェクトを削除しようとしていますが、このエラーが発生します。それはDeleteObject()はEF5中に存在していないとして、私はRemove()メソッドを使用していますObjectStateManager
で見つからなかったため、 オブジェクトを削除することはできません。 誰かが私が逃しているものを助けることができますか?エンティティフレームワーク5のObjectStateManagerにオブジェクトが見つかりませんでしたので、オブジェクトを削除できません

これは

localDb.Customers.Remove(new Customer() { CustomerId = id }); 
       localDb.SaveChanges(); 

私は削除に状態を変更するには、MSDNからしようとした別のものを削除するには機能しません。しかしここでは、すべてのフィールドが存在する必要があるというエラーが返されます。完全なレコードを取得して削除する必要がありますか?

var customer = new Customer(){ CustomerId = id }; 
       localDb.Customers.Attach(customer); 

       localDb.Entry(customer).State = EntityState.Deleted; 
       localDb.SaveChanges(); 

入力はありますか?

答えて

24

データベースから行をフェッチして削除することはできますが、これでデータベースが2回往復します。

ヒットしたい場合は、Attachの2番目のバージョンが動作します(エンティティがまだコンテキストに読み込まれていない場合)。

エラーは、データベースに書き込む前に実行されるEF検証によって発生します。

あなたはこのように一時的にオフにすることができます:

bool oldValidateOnSaveEnabled = localDb.Configuration.ValidateOnSaveEnabled; 

try 
{ 
    localDb.Configuration.ValidateOnSaveEnabled = false; 

    var customer = new Customer { CustomerId = id }; 

    localDb.Customers.Attach(customer); 
    localDb.Entry(customer).State = EntityState.Deleted; 
    localDb.SaveChanges(); 
} 
finally 
{ 
    localDb.Configuration.ValidateOnSaveEnabled = oldValidateOnSaveEnabled; 
} 
+0

私のコンセプトを改善してくれたNicholasに感謝します.SQL側ではなくEF側で検証が行われるのはなぜですか?この設定は私には大事なものだから1ヒットのための唯一の方法です...何かが間違っていれば私を修正してください.. –

+0

これまでのところ、これはDbへの2回のトリップを引き起こすことなく私が信じる唯一の答えです。したがって、これをパフォーマンスの点で回答としてください。 –

+0

northwind.Entry(エンティティ).State = System.Data.Entity.EntityState.Deleted; 固定、ありがとう – balron

2

これを行うだけですか?

var customer = localDb.Customers.Single(o => o.CustomerId == id); 
localDb.Customers.Remove(customer); 
localDb.SaveChanges(); 
+0

はい、プライマリキーのみのエンティティは削除できませんか?私たちはプライマリキーなどをその行に設定できますか? –

+0

2番目の例では、実際に動作する必要があります。必要なフィールドの一時的なデフォルト値を設定して削除しようとしましたか?それらの値は重要ではありません。とにかくオブジェクトを削除するので、プライマリ(エンティティ)キーはすべて正確である必要があります。 –

6

あなたは、データベースからオブジェクトを取得した場合は、により削除することができますので、それがすでにコンテキストに添付ます:

db.myTable.Remove(model); 

けど
モデルを編集または削除して投稿で投稿した場合、またはデータベースへの2回のトリップを避けるために自分で生成した場合は、EFはそれを知らず、上記の行でエラーが発生します。 .. ObjectStateManagerで見つかった)ので、あなたはでEFを知らせるために「削除」にその状態を設定しない:私はこの質問はかなり古いです知っているが、上記のいずれもが、以来、私のために働いていない

//generate it yourself if not posted from edit/delete view 
//var model = new Model { Id = 123 }; 

//set to delete 
db.Entry(model).State = EntityState.Deleted; 
db.SaveChanges(); 
0
public T Delete<T>(T obj) where T : class 
     { 
      T existing = context.Set<T>().Find(GetKeys(obj, context)); 

      if (existing != null) 
      { 
       context.Set<T>().Remove(existing); 
       context.SaveChanges(); 
       return existing; 
      } 
      return null; 
     } 

private object[] GetKeys<T>(T entity, DbContext context) where T : class 
     { 
      ObjectContext objectContext = ((IObjectContextAdapter)context).ObjectContext; 
      ObjectSet<T> set = objectContext.CreateObjectSet<T>(); 
      var keyNames = set.EntitySet.ElementType 
                 .KeyMembers 
                 .Select(k => k.Name).ToArray(); 
      Type type = typeof(T); 

      object[] keys = new object[keyNames.Length]; 
      for (int i = 0; i < keyNames.Length; i++) 
      { 
       keys[i] = type.GetProperty(keyNames[i]).GetValue(entity, null); 
      } 
      return keys; 
     } 
0

私は一度に複数のクラス/サービスからレジスタを削除していましたが、それぞれが独自のデータベース接続コンテキストをインスタンス化していました。

私が解決したのは、最初に作成されたコンテキストをデータベースにアクセスするクラス/サービスの残りの部分に送信することでした。

たとえば、私のserviceAはレジスタのいくつかを削除し、serviceBserviceCを呼び出してレジスタで同じことを行う予定でした。

私はその後serviceAに私のレジスタを削除し、パラメータとしてserviceBからserviceAserviceC上で作成されたコンテキストを渡します。

関連する問題