2016-08-07 8 views
0

私は変更して保存しているエンティティを持っています。 2つのプロパティがあり、両方が変更されています。私は両方がnullではなく、私が意図したものに設定されていることを確認しました。ただし、データベースに表示すると、最初のものだけが変更されます(列一部)、もう一方は変更されません(列ThingId)。エンティティはその列を更新しますが、外部キーを持つ列は更新しません

public class Holder 
{ 
    public string Some { get; set; } 
    public Thing Thing { get; set; } 
} 

public class Thing 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<Holder> Holders { get; set; } 
} 

保存は以下の方法で行われます。

model.Holders.Attach(holder); 
model.Entry(holder).State = EntityState.Modified; 
model.SaveChanges(); 

これらの関係は、以下の方法でFluent APIを使用して定義されます。

builder.Entity<Holder>() 
    .HasOptional(_ => _.Thing) 
    .WithMany(_ => _.Holders) 
    .Map(_ => _.MapKey("ThingId")); 

地球上で何が欠けていますか?新しい保有者を作成するときに問題は発生しません。更新しようとしているときのみ。

+0

テーブルのキーは何ですか?あなたはFKを変更するために何をしましたか? – DevilSuichiro

+0

@DevilSuichiroキーは* Id *(整数値の同一性)です。 FKへの変更は、関連するオブジェクトのインスタンスを割り当てることによって行われます(オリジナルのエンティティを**作成するときと同じように**更新**を行います)。 –

+0

あなたは実際にあなたのコンテキストにホルダーをつけているので、変更はその外で行われますか?物事はあなたの文脈の一部ですか?あなたのエントリが正しく保存されているので、私は物事があなたの文脈の一部ではないと思うので、参照整合性チェックは成功します。そのため、EFは何かをしなければならないということを知らず、事物は文脈の一部ではなく、ナビゲーション特性は非EF法によって変化しました(私は信じています)。何かをあなたのコンテキスト(変更なし)に添付してからmodel.ChangeTracker.DetectChanges()を呼び出すとどうなりますか? – DevilSuichiro

答えて

0

私はこの問題を解決するための3つの方法を提案します。

最初に、EFからコントロールの一部を取り込み、自分で接続を管理しています。基本的には、外部キーを運ぶ明示的なフィールドを導入し、設定されているフィールドを明示的に参照する必要があります。

EFは更新を管理することができますが、これを行う方法を非常に明示することができます。原則として、エンティティを追加、操作、削除されたものとして扱うように指示する必要があります。

最後に、ORMパラダイムに対するオブジェクト指向のアプローチであるため、エンティティを認識しないEFの問題を修正することです。あなたのクラスでは、比較メソッドが実装されていること(平等、ハッシュ制御などのためのメソッドがあります)は見当たりません。もしそれらをGoogleにすれば、EFが依存しているたくさんのおいしさがあります私たちは通常、ちょっとうんざりしています(そして、コンピュータが直感的に私たちを助けるので、それを取り去ります)。

また、免責事項もあります。私は何度もEFで十分ではないこと、そして2つの初期の方法のうちの1つを適用しなければならないということを何度も聞いてきました。回顧的には、コードは常に別の場所にあるコードであることが判明しました(忘れてしまったのは、実装上、混乱したり、ユニークでないID、または単にバグのマイグレーションの更新箇所ではない)。私はそれがここやどこにも当てはまらないと言っているわけではありません。私は他の人の証言以外に、他に示唆するデータがないと言っています。

1

は、あなたが言うとき

model.Entry(holder).State = EntityState.Modified; 

EFは、ホルダエンティティにおけるスカラーが変更されていることを理解しています。

これで、 "Thing"も変更されたことをEFに知らせたいと考えています。だから、明示的に言って、それを述べなければならないでしょう:

model.Entry(holder.Thing).State = EntityState.Modified; 

ORあなたがこれを行うにはしたくないなら、あなたはあなたのモデルにThingIDのプロパティを追加し、同様にそれを移入する必要があります。

EFの状態を理解するためにhttps://www.safaribooksonline.com/library/view/programming-entity-framework/9781449331825/ch04s03.htmlに行くことができます。

+1

'model.Entry(holder.Thing).State = EntityState.Modified;'エンティティ 'holder.Thing'の状態を設定します。変更すると、EFは 'Things'テーブルの更新クエリを生成します。関係フィールド 'Holders.ThingId'には影響しません。 – bubi

1

デタッチされたオブジェクトの操作は非常に難しいです。
いずれにしても、外部キーのプロパティを追加して処理する方法があります(プロパティを追加するだけではありません)。詳細については、他の回答を参照してください。分離したエンティティで作業したい場合は、これが最良の選択だと思います。あなたがn-mの関係(HasMany WithMany)で作業する必要がある場合は、動作しません。

別の解決策は、この(これは、nmの関係でも動作します)

context.Holders.Attach(holder); 
context.Entry(holder).State = EntityState.Modified; 


var manager = ((IObjectContextAdapter)context).ObjectContext.ObjectStateManager; 
manager.ChangeRelationshipState(holder, holder.Thing, "Thing", EntityState.Added); 

context.SaveChanges(); 

は、このソリューションについての問題は、EFはこの

update [Holders] 
set [Some] = @p0, [ThingId] = @p1 
where (([Id] = @p2) and [ThingId] is null) 

@p0 = "Holder updated" 
@p1 = 100 
@p2 = 200 

に似更新クエリを生成していることである(どこを見ています

更新方法をこれに変更すると(読みやすくなります)、同様の現象が発生します。

var thing = holder.Thing; 
holder.Thing = null; 
var attachedHolder = context.Holders.Attach(holder); 
attachedHolder.Thing = thing; 
context.Entry(holder).Property("Some").IsModified = true; 
context.SaveChanges(); 

は、この場合にも発生した更新クエリを使用すると、(取り外し可能)、オリジナル事を知っている必要があり、両方の場合で、だから、

update [Holders] 
set [Some] = @p0, [ThingId] = @p1 
where (([Id] = @p2) and [ThingId] is null) 

@p0 = "Holder updated" 
@p1 = 100 
@p2 = 200 

です。あなたはそれを知っている場合は、この方法でコードを変更することができます:私はEFのソースコードのこの部分を読んでいない実際

var thing = holder.Thing; 
holder.Thing = myOldThing; // for example new Thing() {Id = 2} works 
var attachedHolder = context.Holders.Attach(holder); 
attachedHolder.Thing = thing; 
context.Entry(holder).Property("Some").IsModified = true; 
context.SaveChanges(); 

が、私は、この動作は、nmの関係を管理することができます関係ハンドラに関連していると思います(HasMany-WithMany)。この場合、EFは関係の「サポート」テーブルも生成し、主キー列は2つの表の主キー列の合計です。この種のリレーションシップを更新するには、サポートテーブルの主キーの場所が必要です。

関連する問題