【发布时间】:2016-02-08 12:16:25
【问题描述】:
我很难理解 Code First 如何根据模型建立关系。这是模型:
public class Person
{
[Key]
public string PersonName { get; set; }
[Required]
public virtual Nation NationOfBirth { get; set; }
[Required]
public virtual Nation CurrentNationOfResidence { get; set; }
}
public class Nation
{
[Key]
public string NationName { get; set; }
public virtual Person CurrentSecondInCommand { get; set; }
}
起初我在创建数据库时遇到了一个错误,我可以通过添加几个模型构建器命令来解决这个问题:
modelBuilder.Entity<Person>()
.HasRequired(p => p.NationOfBirth)
.WithRequiredDependent()
.WillCascadeOnDelete(false);
modelBuilder.Entity<Person>()
.HasRequired(p => p.CurrentNationOfResidence)
.WithRequiredDependent()
.WillCascadeOnDelete(false);
我还补充说:
modelBuilder.Entity<Nation>()
.HasOptional(n => n.CurrentSecondInCommand)
.WithOptionalDependent()
.WillCascadeOnDelete(false);
现在,当我尝试使用以下代码填充我的数据库时:
var america = new Nation { NationName = "America" };
context.Nations.Add(america);
var bush = new Person { PersonName = "Bush", CurrentNationOfResidence = america, NationOfBirth = america };
var obama = new Person { PersonName = "Obama", CurrentNationOfResidence = america, NationOfBirth = america };
var biden = new Person { PersonName = "Biden", CurrentNationOfResidence = america, NationOfBirth = america };
context.People.Add(bush);
context.People.Add(obama);
context.People.Add(biden);
context.SaveChanges();
在添加 'bush' 时,CurrentNationOfResidence 和 NationOfBirth 属性对他来说都不为空,并且设置为 'america' 对象。但是,一旦添加了“obama”,“bush”上的 CurrentNationOfResidence 和 NationOfBirth 属性都会变为空。一旦添加了“拜登”,“奥巴马”也会发生同样的情况。
如果我检查由此生成的数据库,我看不到在 People 表上创建的任何外键列,但我希望 Code First 自动为 Person 上的两个 Nation 字段生成 2 个外键(这就是我认为我的前两个模型构建器命令会做的事情——来自“WithRequiredDepedent”的描述)。更奇怪的是,数据库中添加了一个名为“America”的 Person,以及一个也称为 America 的 Nation。
如果有人能提供一些关于我的模型的一般建议,我将不胜感激。我意识到我在这里有一个循环关系,但我认为这没关系,因为国家不需要拥有 CurrentSecondInCommand。我意识到这有点复杂(或者说令人费解是一个更好的词),但我认为这是有道理的:
- 一个人必须有一个(国家)NationOfBirth。
- 一个人必须有一个(国家)CurrentNationOfResidence。
- 一个国家可以选择拥有一个(个人)CurrentSecondInCommand。
非常欢迎任何建议,谢谢。
【问题讨论】:
-
为了测试目的,你可以创建像 america1、america2 等 Nation 对象并分配给每个人并测试它
-
另外你必须在 person 类中用 ForeignKey 属性标记 NationOfBirth...
-
@Viru 刚刚尝试了您的第一个建议。发生的情况是添加了三个“人”,分别称为“America1”、“America2”和“America3”(以及三个同名国家)。
-
@Viru WithRequiredDependent() 的注释摘要指出 - “正在配置的实体类型将是依赖的并包含主体的外键。关系目标的实体类型将是主体在关系中。” - 所以我的理解是外键将由我的模型构建器命令生成。当然,在代码中建模的优点之一是您不需要让不必要的外键属性使代码库变得混乱。如果 CF 可以(并且确实)为您做这件事,那么到处添加外键似乎并不优雅。
-
WithRequiredDependant 是对的。您的问题不是这个,而是您正在配置一对一的关系,而实际上您是多对一的
标签: c# .net entity-framework ef-code-first