2011-08-16 13 views
12

私はユーザテーブルを持っています。 CreatedByのようなフィールドの他のテーブルからこのテーブルへの参照があります。オブジェクト 'dbo.User'に重複キーを挿入できません。 r n文が終了しました

問題は、別のテーブルの行(「x」など)を挿入しようとすると、新しいユーザーをユーザーテーブルに挿入しようとしています。

既存のユーザーとしてCreatedByを使用してテーブル 'x'に行を挿入する必要があります。

Entity Frameworkを使用する4.誰も以前のような問題に直面しましたか?

+0

関連質問:http://stackoverflow.com/questions/5449724/entity-framework-code-first-cannot-insert-duplicate-key-in-object-db – Stefan

答えて

31

エンティティを関連エンティティとともに挿入することも、既存のエンティティを参照するだけでエンティティを挿入することもできます。あなたが書いたコードに依存します。

例1:

User user = GetUserFromSomewhere(); 
using (var context = new MyContext()) 
{ 
    Order order = new Order(); 
    order.CreatedBy = user; 

    context.Orders.AddObject(order); 
    // will put both order and related entity user into Added state 
    // because user is not attached to the context 

    context.SaveChanges(); 
    // creates new order and new user and sets the relationship between them 
} 

例2:

using (var context = new MyContext()) 
{ 
    User user = context.Users.SingleOrDefault(u => u.Id == 1); 
    // query attaches this user to this context 
    // user is in state Unchanged now 

    Order order = new Order(); 
    order.CreatedBy = user; 

    context.Orders.AddObject(order); 
    // will put the order into Added state but doesn't touch the 
    // state of already attached related entities -> user remains 
    // in state Unchanged 

    context.SaveChanges(); 
    // creates new order with reference to user, but doesn't create new user 
} 

例3:

User user = GetUserFromSomewhere(); 
using (var context = new MyContext()) 
{ 
    context.Users.Attach(user); 
    // we attach explicitely to the context telling EF thereby 
    // that we know that this user exists in the DB 
    // user is in state Unchanged now 

    Order order = new Order(); 
    order.CreatedBy = user; 

    context.Orders.AddObject(order); 
    // will put the order into Added state but doesn't touch the 
    // state of already attached related entities -> user remains 
    // in state Unchanged 

    context.SaveChanges(); 
    // creates new order with reference to user, but doesn't create new user 
} 

編集

例4:

int userId = GetUserIdFromSomewhere(); 
using (var context = new MyContext()) 
{ 
    var user = new User { Id = userId }; 
    // we create a stub user entity with the correct primary key 
    // It's not necessary to set other properties 
    // to only set the relationship to the order 

    context.Users.Attach(user); 
    // we attach explicitely to the context telling EF thereby 
    // that we know that this user exists in the DB 
    // user is in state Unchanged now 

    Order order = new Order(); 
    order.CreatedBy = user; 

    context.Orders.AddObject(order); 
    // will put the order into Added state but doesn't touch the 
    // state of already attached related entities -> user remains 
    // in state Unchanged 

    context.SaveChanges(); 
    // creates new order with reference to user, but doesn't create new user 
} 
+0

私の問題の優秀な控除。ちょうど私は既に例3を実行していました。唯一の違いは、GetUserFromSomeWhere()経由でユーザーを取得する代わりに、私はパラメータとしてユーザーオブジェクトを渡していました... WCFワイヤー上で...だから私は文脈を失っていました。これによりEntity Frameworkにユーザーオブジェクトも挿入されました。それはそれが既に存在することを知らなかったので。 クライアントからIDを送信し、サーバー側のIDに基づいてユーザーを取得する必要があります。または、モデルに外部キー列を含める必要があります。これを行うには... order.CreatedBy.Id = id; –

+2

@Nilotpal: 'GetUserFromSomeWhere()'は何とかWCFサービスのシミュレーションだった、あるいは一般的には 'user'エンティティが変更を行うコンテキストから切り離されていました。外来キーのプロパティを使うのは一般的には良い考えです。代わりに、 "スタブ"ユーザエンティティで作業し、これをコンテキストに付加することもできます: 'var user = new User {Id = userId}; context.Users.Attach(user); ' 'Attach'ではプライマリキーのプロパティが設定されていることだけが重要です。リレーションシップをオーダーにのみ設定したい場合、他のプロパティは空のままになることがあります。上記の編集セクションの例4を参照してください。 – Slauma

+1

@Slauma - +1。優れた例。 –

関連する問題