".WithMany()和.WithOptional()之间的区别是什么?"

25

下面是两个相似的流利API配置:

WithMany()

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

WithOptional()

的翻译是:

WithOptional()

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

我想表达的是:每个国家都需要具体的货币,但一个货币可以分配给零个、一个或多个国家。

我应该使用上述哪个语句呢?换句话说:.WithMany().WithOptional()运算符之间到底有什么区别?


您是不是想让标题和描述指的是 .WithMany() 和 .WithOptional() 而不是 .HasMany() 和 .HasOptional()?我已经提交了修改。 - Tom Robinson
1个回答

36
如果您的模型看起来像这样:
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);

该代码会在数据库中创建一个外键关系,其中Countries表中的CountryId是主键兼外键,指向同一时间Currencies表中的CurrencyId,因此Countries表只有一个单独的列CountryId。一个Currencies记录可以存在而没有相关的Countries记录。但如果一个Currencies记录有一个相关的Countries记录,则不能超过一个,因为外键是CountryId,它同时也是主键,因此只能在一个记录中出现。因此,关系Currencies -> Countries1-to-0...1

另一个例子...

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

该操作在数据库的Countries表中创建了一个非空且为外键的CurrencyId第二列,该外键是指向Currencies表中的CurrencyId的。这意味着Currencies表记录可能没有关联的Countries记录,或者有一个或多个关联。因为外键现在是另一列而不是主键,所以Countries表中的多行可能具有相同的外键。这里的关系Currencies -> Countries1对0...n

编辑

如果您使用以下代码对两个不同配置的模型进行修改...

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) 中,有点奇怪的是只有第一个国家被存储了,第二个国家被简单地忽略了。实际上,我期望会收到异常。我不确定是否应该将其视为错误。

编辑2

将上面的示例更改为...

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

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

...在“.HasOptional”情况下抛出预期的异常。


3
好的,我明白了。因此,HasOptional() 用于表示 1 <-> 0|1 的关系,而 HasMany() 用于表示 1 <-> 0|n 的关系。太好了,这就是我想知道的。非常感谢! - Ingmar
1
@Ingmar:看一下我的编辑,可能值得知道。我刚刚发现,也许1 <-> 0|1关系存在一个错误。 - Slauma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接