如何声明外键关系在MVC3中使用代码第一entity framework(4.1)?

我一直在寻找关于如何使用代码第一个EF 4.1来声明外键关系和其他约束的资源,但没有多less好运。 基本上我在代码中构build数据模型,并使用MVC3来查询该模型。 一切工作通过MVC这是伟大的(微软的荣誉!),但现在我希望它不工作,因为我需要有数据模型的约束。

例如,我有一个Order对象,它有很多属性是外部对象(表)。 现在我可以创build一个订单没有问题,但无法添加外键或外部对象。 MVC3设置这个没有问题。

我意识到我可以在保存之前在控制器类中自己添加对象,但是如果约束关系未被满足,我希望调用DbContext.SaveChanges()失败。

新的信息

所以,具体而言,我想要在不指定客户对象的情况下保存Order对象时发生exception。 这似乎不是行为,如果我编写的大多数Code First EF文档中描述的对象。

最新的代码:

public class Order { public int Id { get; set; } [ForeignKey( "Parent" )] public Patient Patient { get; set; } [ForeignKey("CertificationPeriod")] public CertificationPeriod CertificationPeriod { get; set; } [ForeignKey("Agency")] public Agency Agency { get; set; } [ForeignKey("Diagnosis")] public Diagnosis PrimaryDiagnosis { get; set; } [ForeignKey("OrderApprovalStatus")] public OrderApprovalStatus ApprovalStatus { get; set; } [ForeignKey("User")] public User User { get; set; } [ForeignKey("User")] public User Submitter { get; set; } public DateTime ApprovalDate { get; set; } public DateTime SubmittedDate { get; set; } public Boolean IsDeprecated { get; set; } } 

这是我现在得到的错误,当访问患者VS生成的视图:

错误信息

types为“PhysicianPortal.Models.Order”的属性“Patient”上的ForeignKeyAttribute无效。 在依赖types“PhysicianPortal.Models.Order”上找不到外键名称“Parent”。 名称值应该是逗号分隔的外键属性名称列表。

问候,

圭多

如果你有一个Order类,那么添加一个引用你模型中另一个类的属性,例如Customer就足以让EF知道这里有一个关系:

 public class Order { public int ID { get; set; } // Some other properties // Foreign key to customer public virtual Customer Customer { get; set; } } 

您可以始终明确设置FK关系:

 public class Order { public int ID { get; set; } // Some other properties // Foreign key to customer [ForeignKey("Customer")] public string CustomerID { get; set; } public virtual Customer Customer { get; set; } } 

ForeignKeyAttribute构造函数接受一个string作为参数:如果将它放在一个外键属性上,它代表了关联的导航属性的名称。 如果将其放在导航属性上,则表示关联外键的名称。

这意味着什么,如果您将ForeignKeyAttribute放置在Customer属性上,该属性将在构造函数中使用CustomerID

 public string CustomerID { get; set; } [ForeignKey("CustomerID")] public virtual Customer Customer { get; set; } 

基于最新的代码编辑你得到这个错误,因为这一行:

 [ForeignKey("Parent")] public Patient Patient { get; set; } 

EF将查找一个名为Parent的属性,将其用作外键实施者。 你可以做2件事情:

1)删除ForeignKeyAttribute并将其replace为RequiredAttribute以根据需要标记关系:

 [Required] public virtual Patient Patient { get; set; } 

使用RequiredAttribute装饰一个属性也有一个很好的副作用:数据库中的关系用ON DELETE CASCADE创build。

我也build议使属性virtual启用延迟加载。

2)创build一个名为Parent的属性,将作为一个外键。 在这种情况下,将其称为“ ParentID可能更有意义(您还需要更改ForeignKeyAttribute的名称):

 public int ParentID { get; set; } 

根据我在这种情况下的经验,尽pipe反其道而行:

 [ForeignKey("Patient")] public int ParentID { get; set; } public virtual Patient Patient { get; set; } 

您可以通过以下方式定义外键:

 public class Parent { public int Id { get; set; } public virtual ICollection<Child> Childs { get; set; } } public class Child { public int Id { get; set; } // This will be recognized as FK by NavigationPropertyNameForeignKeyDiscoveryConvention public int ParentId { get; set; } public virtual Parent Parent { get; set; } } 

现在,ParentId是外键属性,并定义了子对象与现有父对象之间的必需关系。 保存孩子而不是父母会抛出exception。

如果您的FK属性名称不包含导航属性名称和父级PK名称,则必须使用ForeignKeyAttribute数据注释或stream畅API来映射关系

数据注释:

 // The name of related navigation property [ForeignKey("Parent")] public int ParentId { get; set; } 

stream利的API:

 modelBuilder.Entity<Child>() .HasRequired(c => c.Parent) .WithMany(p => p.Childs) .HasForeignKey(c => c.ParentId); 

其他types的约束可以通过数据注释和模型validation来实施。

编辑:

如果你不设置ParentId你会得到一个exception。 这是必需的财产(不可为空)。 如果你只是不设置它,它很可能会尝试发送默认值到数据库。 默认值为0,所以如果你没有Id = 0的客户,你会得到一个exception。