如何声明外键关系在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。