2011-08-24 16 views
13

2つのエンティティが関連していますが、従来のsqlスキーマには基本的に2つのキー列があります(2列キーではありません)。私は '偽のキー'の列に戻る関係を作成する必要があります。 Entity Framework 4.1でこれを宣言的に行う方法はありますか?Entity Framework 4.1 - 非キー列間の関係

Public Class Client 
    Inherits ModelBase 

    <Key(), Required()> 
    Public Property ClientID As Decimal 

    <Required(), StringLength(50)> 
    Public Property ClientCode As String 

    ........ 


Public Class ClientLocation 
    Inherits ModelBase 

    ........ 

    <Required(), StringLength(50)> 
    Public Property ClientCode As String 

    ........ 

    <ForeignKey("ClientCode")> 
    Public Overridable Property Client As Clients.Client 

そして、私は取得していますエラーは次のとおりです。

*一つ以上の検証エラーがモデルの生成中に検出されました: System.Data.Edm.EdmAssociationConstraint:すべての のプロパティの種類で参照制約の従属ロールは、プリンシパルロールの対応するプロパティタイプと同じ でなければなりません。 「ClientLocation」エンティティのプロパティ「ClientCode」のタイプではないプロパティのタイプは 参照制約「ClientLocation_Client」に実体「クライアント」に「CLIENTID」 試合を行います。*

それは私が考えているので」メートル

任意の考え...私は本当にClientLocation.ClientCode> Client.ClientCodeをマップしようとしていたときに、ClientLocation.ClientCode> Client.ClientIDをマップしようとしていますか?

ありがとうございます!

+0

"* ...レガシーSQLスキーマには、基本的に同じテーブルの2つのキー列があります。*": 'Client.ClientCode'はデータベース内のユニークなインデックスを持つ列ですか?または、「2つのキー列...複合キーではない」は何ですか?そして、この独自の列 'Client.ClientCode'に' ClientLocation.Client'を何とかマッピングしたいのですか? – Slauma

+0

テーブルには2つの有効なキーがありますが、2つ目のキーはキーとして識別されず、インデックスもありません。例えば、ClientIDは4であり、ClientCodeは「FOGCREEK」であってもよい。 2つは関連していないか依存していません。 はい、エンティティのキ​​ーとしてマークされていなくても、Client.ClientCodeを使用して元のテーブルにマップする必要があります。 –

+0

ああ、わかりました、そして、 'ClientCode'は普通の列です。一意性はビジネスロジックによって間違いなく確実に保証されます。私はLadilavの答えが最終的な言葉であることを恐れています。 – Slauma

答えて

3

エンティティフレームワークは、プリンシパルテーブルの全プライマリキーとそれに対応する列(外部キー)との間に関係が構築されることを要求します。

+0

したがって、テーブルと列の名前を「マップ」するのと同じ方法で関係を「マップ」する方法はありません。 –

+0

データベースと同じ方法でリレーションをマップする必要があります。データベースにテーブルが正しく設定されていない場合、EFはそれを修正できません。 –

+1

この回答はおそらく正しいとはいえ、私はまだコンセンサスなしでそれを受け入れるつもりはない。リレーションシップフィールドをオーバーライドするために、データアノテーションおよびに類似したメソッドがないことを誰かが確認できますか? –

0

(これはラディスラフの答えへの唯一の付録で、受け入れ、恵みが私の答えに行ってはいけません。)

、このような機能は、これまでのEFで実装されるならば、私は驚くだろう。どうして?リレーショナルデータベースでもこのような関係を作成することさえできないからです。リレーショナルDB内の外部キー関係(少なくともSQL Serverとおそらくほとんどまたはすべて)では、プリンシパル側は、の主キーであるか、一意のキー制約を持つ列であることが要求されます。外部キーはプリンシパルテーブルのという一意の行を参照することになっているので意味があります。

現在、EFでは一意のキー列との関係、つまり主キー列との関係もサポートされていません。これは将来サポートされる可能性のあるものです。しかし、一意でないキーや非主キー以外のキーとの外部キー関係のサポートは、私にとっても意味をなさないようです。

プリンシパルテーブルのターゲット列の値が一意でない場合はどうなりますか?例えば、 - 熱心な負荷をかけたいときに例外をしますか?ClientLocation.Client - "外部キーが一意のターゲット"または警告"を参照していないため、ナビゲーションプロパティ 'Client'を読み込めません。私はあなたが望むものをロードしたことを保証することはできません "か何かのようなものですか?

自分の好きなことをしたい場合は、アイデアをあきらめて、ナビゲーションプロパティを削除し、LINQクエリでJoinと多く動作するように指示してください。

0

おそらくアソシエーション属性はあなたの答えです。アソシエーションを使用すると、リレーションの両側でどのキーを使用するかを指定できます。このような

いくつかのコード:

[ForeignKey()] 
[Association("SomeNameForAssociation","TheKeyInThisEntity","TheKeyOnTheAssociationTargetEntity")] 
public virtual Examination Examination { get; set; } 

そして、私はあなたの質問を理解していれば、あなたはコードに変更する必要があります。

Public Class Client 
    Inherits ModelBase 

    <Key(), Required()> 
    Public Property ClientID As Decimal 

    <Required(), StringLength(50)> 
    Public Property ClientCode As String 

    ........ 


Public Class ClientLocation 
    Inherits ModelBase 

    ........ 

    <Required(), StringLength(50)> 
    Public Property ClientCode As String 

    ........ 

    <ForeignKey("ClientCode")> 
    <Association("ClientClientCodes","ClientCode","ClientCode")> 
    Public Overridable Property Client As Clients.Client 

まず "ClientCode":ClientCodeにおけるキー列の名前。 2番目の "ClientCode":使用するClientCodeのキー列の名前。

注:この属性はまだ使用されていませんが、ドキュメントとその名前と引数名は必要に応じて使用してください。

+0

'[Association]'属性がEntity Frameworkに何らかの影響を与えるのではないかと疑います。これは、LINQ to SQLのマッピング属性にすぎません。 – Slauma

2

これは不可能な場合でも、so(C#)のようなLINQクエリを使用して2つのテーブルを結合することもできます(このquestionも参照してください)。

var result = from a in ctx.Client 
      join b in ctx.ClientLocation 
      on a.ClientCode equals b.ClientCode 
      select new { Client = a, Location = b }; 

ナビゲーションプロパティClient.ClientLocationおよびClientLocation.Clientが不足しています。それにもかかわらず、このようにするのは少し面倒ですが、それでも可能です。

SQLスキームを拡張したい場合は、ClientLocationClientのような別のテーブルを追加することができます。このテーブルは、ClientとClientLocationの両方に外部キーを持つM:Nテーブルとして機能し、2つは複合キーとして機能します。この行は、しかし、すぐにあなたは、該当するクライアントを持っていない、そしてもちろん、あなたの拡張テーブルを同期するには、クライアントにトリガを定義する必要がありますClientLocationを持っているように失敗します

var client = myClientLocation.ClientLocationClients.First().Client; // there's only one 

あなたがそのようにのようにナビゲートすることができ(C#の)削除をカスケードに設定し、クライアントの前にClientLocationを挿入する必要があります。そうしないと、トリガーは失敗します...全体として、これはかなり危険なルートになる可能性があるという警告を出しています。

関連する問題