如何在MVC3中使用Code First Entity Framework(4.1)声明外键关系?

Gui*_*lmi 99 ef-code-first entity-framework-4.1 asp.net-mvc-3

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

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

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

新的消息

所以,具体来说,当我尝试保存Order对象而不指定客户对象时,我希望发生异常.如果我只是编写大多数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; }
}
Run Code Online (Sandbox Code Playgroud)

这是我在访问患者的VS生成视图时遇到的错误:

错误信息

类型为"PhysicianPortal.Models.Order"的属性"Patient"上的ForeignKeyAttribute无效.在依赖类型"PhysicianPortal.Models.Order"上找不到外键名称"Parent".Name值应该是以逗号分隔的外键属性名称列表.

问候,

圭多

Ser*_*eit 155

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

public class Order
{
    public int ID { get; set; }

    // Some other properties

    // Foreign key to customer
    public virtual Customer Customer { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

您始终可以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; }
}
Run Code Online (Sandbox Code Playgroud)

ForeignKeyAttribute构造函数采用一个字符串作为参数:如果你将它放在一个外键属性它代表关联的导航属性的名称.如果将其放在导航属性上,则表示关联外键的名称.

这意味着,如果您ForeignKeyAttributeCustomer属性放在属性上,该属性将包含CustomerID在构造函数中:

public string CustomerID { get; set; }
[ForeignKey("CustomerID")]
public virtual Customer Customer { get; set; }
Run Code Online (Sandbox Code Playgroud)

基于最新代码的编辑 由于这一行你得到了这个错误:

[ForeignKey("Parent")]
public Patient Patient { get; set; }
Run Code Online (Sandbox Code Playgroud)

EF将查找一个名为Parent"外键实施者" 的属性.你可以做两件事:

1)取下ForeignKeyAttribute并更换,RequiredAttribute以便根据需要标记关系:

[Required]
public virtual Patient Patient { get; set; }
Run Code Online (Sandbox Code Playgroud)

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

我还建议使该属性virtual启用延迟加载.

2)创建一个名为Parent的外部属性作为外键.在这种情况下,例如调用它可能更有意义ParentID(您还需要更改名称ForeignKeyAttribute):

public int ParentID { get; set; }
Run Code Online (Sandbox Code Playgroud)

根据我在这种情况下的经验,虽然它反过来更好地使用它:

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

public virtual Patient Patient { get; set; }
Run Code Online (Sandbox Code Playgroud)


Lad*_*nka 29

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

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; }
}
Run Code Online (Sandbox Code Playgroud)

现在,ParentId是外键属性,并定义了子级和现有父级之间所需的关系.保存没有现有父级的孩子会抛出异常.

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

数据注释:

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

流畅的API:

modelBuilder.Entity<Child>()
            .HasRequired(c => c.Parent)
            .WithMany(p => p.Childs)
            .HasForeignKey(c => c.ParentId);
Run Code Online (Sandbox Code Playgroud)

其他类型的约束可以通过数据注释和模型验证来实施.

编辑:

如果你没有设置,你会得到一个例外ParentId.它是必需的属性(不可为空).如果您只是不设置它,它很可能会尝试将默认值发送到数据库.默认值为0,因此如果您没有Id = 0的客户,您将获得例外.