エンティティフレームワークを使用して主キー値を更新する

.net entity-framework sql-server vb.net

質問

エンティティフレームワーク内から複合主キーの値を1つ更新しようとしていますが、「プロパティ 'CustomerID'はオブジェクトのキー情報の一部であり、変更できません」というエラーが発生します。

これが私のコードです:

Dim customer As Customer = (From c In db.Customer Where c.CustomerID = "xxx" AndAlso c.SiteKey = siteKey).FirstOrDefault
customer.CustomerID = "fasdfasdf"
db.SaveChanges()

簡単すぎるようです。エンティティフレームワーク内で主キーを更新できないのは本当ですか?トピックに関するドキュメントが見つかりません。ありがとうございます。

受け入れられた回答

できないし、正当な理由で。 KMのコメントを見てください。

1つは匿名データを含むテーブル、もう1つはログイン後に実際のユーザーデータを格納するテーブルを用意することです。

あるいは、あなたが(私がこれまでにテストしたことも行ったこともない)このようなテーブルレイアウトを持つことができるでしょう。

---Customers----
AutoNumber PK <- This links to all other tables in your database, and does NOT change.
CustomerID  <- This can change.
CustomerType <- Anonymous or logged in.  

そして彼らがログインしたときあなたはCustomerTypeとCustomerIDをあなたが必要とするものに変更します。

そのため、クエリは次のようになります。

Dim customer As Customer = (From c In db.Customer _
                            Where c.CustomerID = {Some temp ID} _
                            AndAlso c. CustomerType = "Anonymous").FirstOrDefault
// After user logs in.
customer.CustomerID = {Make a new user ID here}
customer.CustomerType = "LoggedIn" {or what ever}
db.SaveChanges()

自動番号主キー変更されないことに注意してください。これは、Customersテーブルとの関係にあるテーブルがまだ機能し、主キーを段階的に更新する必要がないようにするためです(鉛筆で目をそらすようなものです)。


人気のある回答

私は博士号を持っていますcs - データベースの分野では、この答えはプログラマーの視点とは少し異なります。 Oliver Hanappiを尊重しても、代理キーでない場合、キーは変わる可能性があり、ときどき変わります。例:自然キーまたは複合キー。例えば。あなたのSSNをアメリカで変更することは可能です。しかし、何年にもわたってダウンしてきた多くのプログラマーは、これを変更不可能なキーと見なし、それをそのまま使用するでしょう。外部キーで構成されている複合主キーを変更する方がはるかに一般的です。

私は三元関係を持つデータベースを扱っています。具体的には3つのエンティティ(外部キーはそれぞれのテーブルの主キーを代理します)。ただし、3番目のエンティティを変更しながら2つのエンティティ間の関係を維持するには、交差テーブル(MSDNでは純粋結合テーブルとも呼ばれる)の主キーの一部を変更する必要があります。これは有効な設計であり、3項関係の交差テーブルを削除し、それを2つの2項関係テーブル(独自の代理キーを持つ場合がある)に置き換えることによってのみ改善できます。 EFはこの罰金を処理します。この設計変更は、(多→多) - >多またはParent1-Parent2 - > Child-grandchildモデルになります(それが明確でない場合は、以下の例を読んでください)。各関係は実際には一対多のrelationshiopであるため、エンティティフレームワークはこれでうまく動作します。しかし、DBの観点から見ればそれはクレイジーなデザインです。その一例をお見せしましょう。

コース、クラスルーム、インストラクターがクラス内で互いに関連付けられているとします。クラスには、外部キーとしてCourseID、ClassroomID、InstructorIDを含めることができ、3つすべてを含む複合主キーを含めることができます。明確で簡潔な三元モデル(3元関係)であるが、それを二項関係に分割することができる。これは二つの交差テーブルを与えるでしょう。代理キーを追加すると、次のようにEFが満たされます。

クラス( SurrogateKeyClassInstructorIDCourseID

ClassRoomUsed( SurrogateKeyClassroomUsedSurrogateKeyClassClassRoomID

このデザインの問題点は、同じコースとインストラクターを複数回関連付けることができるということです。これまでのモデルでは避けられていました。この問題を回避するには、データベースに2つのIDフィールドの一意性に関する制約を追加しますが、最初に代理キーのみを扱う場合にこれを実行するのはなぜでしょうか。しかし、この解決策は私が言うことができるのと同じくらいうまくいくでしょう。しかしながら、これは論理データベースの設計ではありません。なぜならDBには不自然なユニークな制約が必要だからです。

しかし、データベースを変更したくない場合やデータベースを変更できない場合は、 2つ目の解決策があります 。交差/関連テーブルは、2つ以上のエンティティをリンクするリンクです。変更した場合は、関連付けを削除して、適切な外部キー(ナビゲーションプロパティ)を持つ新しい関連付けを再作成します。つまり、どの関係においても子エンティティを要求することは許可されませんが、これは非常に一般的です。

私はEntity Framework(将来的に)が欲しいときに優雅なDBモデルを設計できる私達の誰かが交差/関連テーブルのキーの部分を変更することを可能にすることを提案するでしょう!

自由のためのもう一つの例:

学生、コース、学年協会を考えてみましょう。学生は学年を介してコースに関連付けられています。通常、これはStudentとCourseとの間のgradeと呼ばれる関連テーブルの追加フィールドを持つ多対多関連です(関連テーブルにはgradeのようなペイロードデータがあり、交差テーブルにはペイロードがありません)。一箇所でリース):

学生( StudentID 、....)

コース( CourseID 、...)

受講学生IDコースID 、学年)

誰かがドロップダウンからデータ入力エラーをして生徒を間違ったクラスに入れた場合、後でドロップダウンを選択して別のコースを選択することで後で変更するのが好きです。バックグラウンドでは、テイクテーブルからEFオブジェクトを削除し、グレードがあればそれを失うことなく再作成する必要があります。単に外部キーCourseIDを変更するのがより良い代替手段のようです。もしこれが人為的に思われるなら、あなた自身の協会に来てください、しかし教授としてそれは私にとって自然でした。

結論:一連の関係がある場合は、カスケードやFKの変更を許可しない方が良い場合がありますが、 一般的にベストプラクティスとして推奨されていなくても、必要な場合には共振/論理シナリオがあります。

この問題は、モデルのナビゲーションプロパティまたはキープロパティをそれぞれ変更しているかどうかに応じて、次のような例外が発生する可能性があります。

参照整合性制約違反が発生しました。参照整合性制約の一部である主キープロパティは、依存オブジェクトが未変更の場合、アソシエーションのプリンシパルオブジェクトに設定されていない限り変更できません。プリンシパルオブジェクトを追跡し、削除対象としてマークしないでください。

プロパティ 'X'はオブジェクトのキー情報の一部であり、変更できません。



Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ