web-dev-qa-db-ja.com

.WithMany()と.WithOptional()の違いは?

以下は、2つの同様の流暢なAPI構成です。

WithMany()

_modelBuilder.Entity<Country>()
            .HasRequired(cou => cou.Currency)
            .WithMany()
            .WillCascadeOnDelete(false); 
_

WithOptional()

_modelBuilder.Entity<Country>()
            .HasRequired(cou => cou.Currency)
            .WithOptional()
            .WillCascadeOnDelete(false);
_

ここで表現しようとしているのは、すべてのCountryには具体的なCurrencyが必要ですが、Currencyはゼロ、1つ、または複数の国に割り当てることができます。

上記のステートメントのどれを使用する必要がありますか?言い換えれば、.WithMany()演算子と.WithOptional()演算子の違いは正確には何ですか?

24
Ingmar

モデルが次のようになる場合:

public class Country
{
    public int CountryId { get; set; }
    public Currency Currency { get; set; }
}

public class Currency
{
    public int CurrencyId { get; set; }
}

その後.。

modelBuilder.Entity<Country>()
            .HasRequired(cou => cou.Currency)
            .WithOptional()
            .WillCascadeOnDelete(false);

...データベースに外部キー関係を作成します。ここで、CountryIdテーブルのCountriesは主キーであり、CurrencyIdテーブルのCurrenciesへの外部キーです。同時に、Countriesテーブルには単一の列のみCountryIdがあります。 Currenciesレコードは、関連するCountriesレコードがなくても存続できます。ただし、Currenciesレコードに関連するCountriesレコードがある場合、外部キーは同時に主キーであるCountryIdであるため、1つしか存在できません。 1つのレコードで。したがって、関係Currencies -> Countries1-to-0...1

他の例.。

modelBuilder.Entity<Country>()
            .HasRequired(cou => cou.Currency)
            .WithMany()
            .WillCascadeOnDelete(false);

...データベースのCurrencyIdテーブルに2番目の列Countriesを作成します。これは、null許容ではなく、CurrencyIdへの外部キーです。 Currenciesテーブルの。したがって、ここでは、外部キーが主キーと同一ではなく別の列になっているため、Currenciesレコードに関連するCountriesレコードがないか、1つまたは複数ある可能性があります。したがって、Countriesテーブルの複数の行が同じ外部キーを持つ可能性があります。関係 Currencies -> Countries ここは 1-to-0...n

編集

異なる構成の2つのモデルに対して次のコードを使用すると...

Country country1 = new Country();
Country country2 = new Country();
Currency currency = new Currency();

country1.Currency = currency;
country2.Currency = currency;

context.Countries.Add(country1);
context.Countries.Add(country2);

context.SaveChanges();

...次に、2番目のケース(.WithMany)が機能します。データベースに2つの新しい国と1つの通貨を取得します。

ただし、少し奇妙なことに、2番目のケース(.HasOptional)では、最初の国のみが保存され、2番目の国は単に無視されます。実際、私は例外が発生することを期待していました。それをバグと見なす必要があるかどうかはわかりません。

Edit2

上記の例の順序を...に変更します。

context.Countries.Add(country1);
context.Countries.Add(country2);

country1.Currency = currency;
country2.Currency = currency;

...「。HasOptional」の場合に予期される例外をスローします。

36
Slauma