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

发布于 2024-10-29 16:46:18 字数 1533 浏览 3 评论 0原文

我一直在寻找有关如何使用代码优先 EF 4.1 声明外键关系和其他约束的资源,但运气不佳。基本上我是在代码中构建数据模型并使用 MVC3 来查询该模型。一切都通过 MVC 运行,这很棒(感谢 Microsoft!),但现在我希望它不起作用,因为我需要数据模型约束。

例如,我有一个 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; }
}

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

错误消息

属性上的ForeignKeyAttribute 类型为“患者” “PhysicianPortal.Models.Order”不是 有效的。外键名称“Parent” 未在依赖类型上找到 'PhysicianPortal.Models.Order'。这 名称值应该以逗号分隔 外键属性名称列表。

问候,

吉多

I have been searching for resources on how to declare foreign key relationships and other constraints using code first EF 4.1 without much luck. Basically I am building the data model in code and using MVC3 to query that model. Everything works via MVC which is great (kudos to Microsoft!) but now I want it NOT to work because I need to have data model constraints.

For example, I have a Order object that has a ton of properties that are external objects (tables). Right now I can create an Order no problem, but without being able to add the foreign key or external objects. MVC3 sets this up no problem.

I realize that I could just add the objects myself in the controller class prior to save, but I would like the call to DbContext.SaveChanges() to fail if the constraint relationships have not been met.

NEW INFORMATION

So, specifically, I would like an
exception to occur when I attempt to
save an Order object without
specifying a customer object. This
does not seem to be the behavior if I
just compose the objects as described
in most Code First EF documentation.

Latest code:

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; }
}

This is the error I get now when accessing the VS generated view for Patient:

ERROR MESSAGE

The ForeignKeyAttribute on property
'Patient' on type
'PhysicianPortal.Models.Order' is not
valid. The foreign key name 'Parent'
was not found on the dependent type
'PhysicianPortal.Models.Order'. The
Name value should be a comma separated
list of foreign key property names.

Regards,

Guido

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

暖伴 2024-11-05 16:46:18

如果您有一个 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 构造函数采用字符串作为参数:如果将其放置在外键属性上,它表示关联导航属性的名称。如果将其放置在导航属性上,它表示关联外键的名称。

这意味着,如果您将 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 并将其替换为 RequiredAttribute 以将关系标记为必需:

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

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

我还建议将属性设置为虚拟以启用延迟加载。

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

public int ParentID { get; set; }

根据我在这种情况下的经验尽管反过来使用效果更好:

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

public virtual Patient Patient { get; set; }

If you have an Order class, adding a property that references another class in your model, for instance Customer should be enough to let EF know there's a relationship in there:

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

    // Some other properties

    // Foreign key to customer
    public virtual Customer Customer { get; set; }
}

You can always set the FK relation explicitly:

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; }
}

The ForeignKeyAttribute constructor takes a string as a parameter: if you place it on a foreign key property it represents the name of the associated navigation property. If you place it on the navigation property it represents the name of the associated foreign key.

What this means is, if you where to place the ForeignKeyAttribute on the Customer property, the attribute would take CustomerID in the constructor:

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

EDIT based on Latest Code
You get that error because of this line:

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

EF will look for a property called Parent to use it as the Foreign Key enforcer. You can do 2 things:

1) Remove the ForeignKeyAttribute and replace it with the RequiredAttribute to mark the relation as required:

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

Decorating a property with the RequiredAttribute also has a nice side effect: The relation in the database is created with ON DELETE CASCADE.

I would also recommend making the property virtual to enable Lazy Loading.

2) Create a property called Parent that will serve as a Foreign Key. In that case it probably makes more sense to call it for instance ParentID (you'll need to change the name in the ForeignKeyAttribute as well):

public int ParentID { get; set; }

In my experience in this case though it works better to have it the other way around:

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

public virtual Patient Patient { get; set; }
纸短情长 2024-11-05 16:46:18

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

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 是外键属性,定义子级和现有父级之间所需的关系。在父级不存在的情况下保存子级将引发异常。

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

数据注释:

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

Fluent API:

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

可以通过 数据注释和模型验证

编辑:

如果您不设置 ParentId,您将收到异常。它是必需的属性(不可为空)。如果您不设置它,它很可能会尝试将默认值发送到数据库。默认值为 0,因此如果您没有 Id = 0 的客户,您将收到异常。

You can define foreign key by:

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; }
}

Now ParentId is foreign key property and defines required relation between child and existing parent. Saving the child without exsiting parent will throw exception.

If your FK property name doesn't consists of the navigation property name and parent PK name you must either use ForeignKeyAttribute data annotation or fluent API to map the relation

Data annotation:

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

Fluent API:

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

Other types of constraints can be enforced by data annotations and model validation.

Edit:

You will get an exception if you don't set ParentId. It is required property (not nullable). If you just don't set it it will most probably try to send default value to the database. Default value is 0 so if you don't have customer with Id = 0 you will get an exception.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文