0

Addresses と Visits の 2 つのテーブルが主キーとして同じ値を共有する EF6 データベースを作成しようとしています。Visits は、概念的には Addresses の拡張です。Addresses のほとんどのレコードは Visits に含まれるフィールドを必要としないため、テーブルを分割しています。

コードファーストのアプローチを使用しています。アドレスに関連するコードは次のとおりです。

    public class Address 
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ID { get; set; }

    [ForeignKey( "ID" )]
    public virtual Visit Visit { get; set; }

および訪問の場合:

   public class Visit
   {
    [Key]
    [DatabaseGenerated( DatabaseGeneratedOption.Identity )]
    public int ID { get; set; }

    [ForeignKey("ID")]
    public virtual Address Address { get; set; }

私の調査に基づいて、データコンテキストの OnModelCreating メソッドに以下を含める必要もありました。

    modelBuilder.Entity<Visit>()
        .HasOptional( v => v.Address )
        .WithRequired();

残念ながら、これは機能しません。Addresses からプライマリ インデックスを削除するためのスキャフォールディング コールを削除した後、データベースを正常に更新できます (おそらく、追加移行コードが主キーを「単なる」外部キー フィールドと見なしているため)。しかし、アプリケーションを実行すると、次のエラーが発生します。

列名 'Address_ID' が無効です。列名 'Address_ID' が無効です。

EF6 での私の限られた経験から、これはフレームワークの奥深くにあるように見え、おそらく Visits テーブルに「Address_ID」という名前のフィールドがあると予想されます (私が見た「テーブル名」_「フィールド名」命名構造に基づく)その他の暗黙的に追加されたフィールド)。

私がやろうとしていることは可能ですか?もしそうなら、私は構成で何が欠けていますか?

追加情報

残念ながら同じエラーが引き続き発生するbubiの提案されたソリューションを試してみると、OnModelCreatingコードを削除しても、機能的な移行コードが生成されます。

解像度

私はついに、以前に行うべきだったことを行いました。それは、爆発していたクエリによって生成された実際の T-SQL コードを調べることです。問題は Visit/Address リンケージにあるのではなく、別のテーブルを含む完全に別の関係にあることがわかりました。どうやら、途中のどこかで、他のテーブル (投票者) に Address_ID 外部キー フィールドがあると EF に思わせるようなことをしたようです。実際には、Address/Voter の関係は Voter.AddressID フィールドに結び付けられるべきでしたし、元々結び付けられていました。

多数の移行を巻き戻そうとするのではなく、データベースを吹き飛ばし、移行を吹き飛ばして、最初からやり直すことにしました。データベースを再作成した後、bubi の提案を使用して、バックアップからデータをリロードすると、ほら、仕事に戻りました。

完全を期すために、住所と訪問の関係を正しく機能させるために、OnModelCreating メソッド呼び出しに入れなければならなかったコードを次に示します。

modelBuilder.Entity<Visit>()
    .HasRequired( v => v.Address )
    .WithRequiredDependent( a => a.Visit );

modelBuilder.Entity<Address>()
    .HasRequired( a => a.Visit )
    .WithRequiredPrincipal( v => v.Address );

Address テーブルのすべてのエントリが Visit テーブルにエントリを持っているわけではないため、WithRequiredPrincipal/WithRequiredDependent を使用できるようにするために HasRequired を使用する必要がある理由について少し混乱しています。それは「必須」ではなく「任意」のようです。しかし、それは機能しているように見え、おそらく「必要な」部分は、データベース自体ではなく、データベースの EF のモデルの内部にあるだけです。

4

2 に答える 2

1

bubiが言及したことに加えて、あなたのステートメントは、逆のプロパティとしてmodelBuilder言及していないという点でモデルと矛盾しています。Address.Visitそのため、プロパティが別の関係を表していると考え、Address_IDその関係の列を作成しようとします。

あなたが持っている必要があります

modelBuilder.Entity<Visit>()

    // from your description sounds like every Visit needs an Address
    .HasRequired(v => v.Address )

    // need to mention the inverse property here if you have one
    .WithOptional(a => a.Visit); 

...または、既に属性を使用しているため、ステートメントを完全に削除するだけで、EF は規則に従ってそれを把握できるはずです。

于 2015-08-13T17:08:49.823 に答える
1

モデルには 2 つの問題があります。
- キーの 1 つだけが自動番号付けできます。もう 1 つのキーは同じ ID を取得する必要があります (これは EF によって個別に行われます)。
- マッピングの問題。
このモデルは機能するはずです。

public class Address
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public string Description { get; set; }

    public virtual Visit Visit { get; set; }
}

public class Visit
{
    public Visit()
    {
        Address = new Address();
    }

    [Key]
    [ForeignKey("Address")]
    public int Id { get; set; }

    public string Description { get; set; }

    public virtual Address Address { get; set; }
}

使用例

            var visit = new Visit
            {
                Description = "Visit",
                Address = {Description = "AddressDescription"}
            };

            db.Visits.Add(visit);

            db.SaveChanges();
于 2015-08-13T13:42:34.123 に答える