Подтвердить что ты не робот

EF 4.1: Разница между .WithMany() и .WithOptional()?

Ниже приведены две аналогичные конфигурации 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, но a Currency может иметь нуль, одну или многие страны, назначенные.

Какое из приведенных выше утверждений я должен использовать? Или, другими словами: в чем же разница между операторами .WithMany() и .WithOptional()?

4b9b3361

Ответ 1

Если ваша модель будет выглядеть так:

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 table имеет только один столбец CountryId. Запись Currencies может жить без соответствующей записи Countries. Но если запись Currencies имеет связанную запись Countries, то не более одного, потому что внешний ключ CountryId является первичным ключом одновременно и поэтому может находиться только в одной записи. Таким образом, отношение Currencies -> Countries равно 1-to-0...1.

Другой пример...

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

... создает второй столбец CurrencyId в таблице Countries базы данных, которая не является нулевой и является внешним ключом для CurrencyId таблицы Currencies, Поэтому здесь возможно, что запись Currencies не имеет связанной записи Countries или одной или нескольких, потому что внешний ключ теперь является другим столбцом, не идентичным первому ключу. Поэтому более одной строки в таблице Countries может иметь один и тот же внешний ключ. Связь Currencies -> Countries здесь 1-to-0...n.

Edit

Если вы берете следующий код для двух разных конфигураций моделей...

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();

... тогда работает второй случай (.WithMany): мы получаем две новые страны и одну валюту в базе данных.

Однако немного странно, что во втором случае (.HasOptional) сохраняется только первая страна, вторая просто игнорируется. На самом деле я ожидал получить исключение. Я не уверен, что это нужно рассматривать как ошибку.

Edit2

Изменение порядка в примере выше, чтобы...

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

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

... выбрасывает ожидаемое исключение в случае ".HasOptional".