2

この件に関して多くの質問があることは知っていますが、特定の問題を解決する方法を実際に説明している質問を見つけることができませんでした. これは、解決できない可能性があることを意味すると思います (EF の考え方に「逆行」している可能性があると思います) が、質問する必要があります。

私は3つの(省略された)POCOを持つモデルを持っています:

[Table("People")]
public class Person {
    public int PersonID { get; set; }
    [Required]
    public string PersonName { get; set; }
}

public class Location {
    public int LocationID { get; set; }
    public int LocationTypeID { get; set; }
    public virtual LocationType LocationType { get; set; }
}

public class Van : Location {
    public int PartyID { get; set; }
    public virtual Party Party { get; set; }
}

これらは (省略された) データベース テーブルによって支えられています (これらは手作業で記述されています)。

CREATE TABLE People (
    PersonID INTEGER IDENTITY NOT NULL,
    PersonName VARCHAR(255) NOT NULL,
    PRIMARY KEY (PersonID)
)

CREATE TABLE Locations (
    LocationID INTEGER IDENTITY NOT NULL,
    LocationTypeID INTEGER NOT NULL,
    FOREIGN KEY (LocationTypeID) REFERENCES LocationTypes(LocationTypeID)
)

CREATE TABLE Vans (
    LocationID INTEGER NOT NULL,
    PersonID INTEGER NOT NULL,
    PRIMARY KEY (LocationID),
    FOREIGN KEY (LocationID) REFERENCES Locations(LocationID),
    FOREIGN KEY (PersonID) REFERENCES People(PersonID)
)

LocationTypes見た目は想像できると思います。

Locations型ごとのテーブル階層のルートです。これを強制するためのチェック制約もあります。Vansのようなここでは関係のないものと同様に、場所の一種ですWarehouse

ここで、 aは aVanに属していますPerson。つまり、従業員にバンを発行し、燃料を満タンにするのは従業員の責任であり、クラッシュさせず、顧客のサイトに持っていき、供給がすべて使い果たされたときに追加の商品を注文するのは従業員の責任です。ネジ、ドリル ビット、外装 DC ケーブル。ただし、すべてPersonがバンを持っているわけではなく (一部は 1 つのバンでペアで動作します)、Personテーブルには を指す外部キーがありませんVan。これは逆です。これはある意味では歴史的な事故ですが、状況を非常にうまくモデル化してPersonVanますVan

だから私の質問に:どうすればPersonナビゲーションプロパティをそのVan中に入れることができますか?

public virtual Van Van { get; set; }

私はデータ注釈と流暢な API をいじくり回してきましたが、最も近いものは次のOnModelCreatingとおりです。

modelBuilder.Entity<Van>()
    .HasRequired(v => v.Person)
    .WithOptional(p => p.Van);

残念ながら、これはオブジェクトVanを生成するプロキシをプロパティに設定しようとしLocationます。それは正しいオブジェクトである可能性もありLocationます (私は確認できませんでした) が、それがバンを探していることに気付いていません。PersonIDただし、ルックアップを行うときに照合しようとしている可能性があるとLocationID思います-Fluent APIマッピングがないと、バンがまったく取得されません。これは私が期待することです(すべてのPersonID値は最低LocationID値よりも低いですバンに対応するため、おそらく何も見つかりませんでした)。

Personへの null 可能な外部キーがVanあれば、これは間違いなく非常に簡単でしょVanVanPerson.

したがって、Vanはこの関係を所有しており、Vanプロパティ onPersonは逆ナビゲーション プロパティですが、一方の端がオプションであっても、EF はこの種の 1 対 1 のトリックがあまり得意ではないようです。それを機能させる方法はありますか、それとも妥協を受け入れる必要がありますか?

私たちは通常、Entity Framework に欠けている機能のためにデータベース モデルを妥協することを拒否します。私が本当に必要としているのは、VanVans.PersonID Person= Person.PersonID.

4

1 に答える 1

4

問題は、これが現時点でサポートされていないことです。あなたは、問題がどこで解決されるのかという質問を見つけることができなかったと述べました。このタイプの 1 対 1 の関係を解決するために絶対に必要な一意の制約/候補キーを EF がサポートしていないことに言及する質問を見つけたのだろうか。

データベースでは、従属テーブルの FK が一意である場合にのみ、1 対 1 の関係を実現できます。これは、従属テーブルの FK 列に一意の制約 (インデックス) を配置するか、従属テーブルの PK をプリンシパル テーブルへの FK として使用するという 2 つの方法で実行できます。

EF はデータベースと同じ参照整合性規則を適用しますが、1 対 1 の関係で一意制約がサポートされていない場合、前者の方法はサポートされません。EF は、従属テーブルの PK をプリンシパル テーブルへの FK として使用することによってのみ、1 対 1 の関係をモデル化できます。

一意の制約/候補キーのサポートについては、Data UserVoiceで投票できます。

あなたの特定の問題を解決する方法は?EFをだますことによって。EFに1対多の関係があると考えさせPersonID、テーブルに一意の制約を配置しVanます。Person を次のように更新するよりも:

[Table("People")]
public class Person {
    public int PersonID { get; set; }
    [Required]
    public string PersonName { get; set; }

    public virtual ICollection<Van> Vans { get; set; }

    [NotMapped]
    public Van Van 
    {
        get { return Vans.FirstOrDefault(); }
        set
        {
             Vans.Clear();
             if (value != null)
             {
                 Vans.Add(value);
             }
        }
    }
}

Vansコレクションがまだ公開されているため、これはかなり醜い回避策です。その可視性で遊ぶことができますが、いくつかのことを理解していることを確認してください:

  • Vansパブリックでない場合は、それをマップする必要がありOnModelCreating、そのコンテキストでプロパティを表示できる必要があるか、それを行うマッピング構成を提供する必要があります。詳細については、これこれを確認してください。
  • Vansプロパティは、遅延読み込みをサポートするためにプロキシ作成のルールを破ってはなりません
  • イーガーローディングはVansプロパティを使用する必要があります
于 2012-06-09T10:10:12.890 に答える