实体框架代码首先 - 定义关系/密钥

时间:2011-04-03 21:58:44

标签: entity-framework entity-framework-4.1

我首先使用代码设计我的数据库,我想我需要一些帮助。

我收到此错误:

  

在表'Invoices'上引入FOREIGN KEY约束'SalesOrder_Invoices'可能会导致循环或多个级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY约束   无法创建约束。查看以前的错误。

我正在尝试使用以下关系/键:

--> = 1 to Many Relationship
  1. 客户 - > CustomerLocation
  2. CustomerLocation - > SalesOrder
  3. SalesOrder - >发票
  4. SalesRep - > SalesOrder
  5. PaymentTerm - >客户
  6. PaymentTerm - > SalesOrder
  7. PaymentTerm - >发票
  8. 我试图通过以下标准来定义它们:

    <ClassName><PrimaryKeyID>
    

    示例:Customer具有ID属性,因此在CustomerLocation中我定义了外键,如下所示:

    Public Property CustomerID AS Integer
    

    我所要做的就是定义外键是否正确?我是否还必须为我定义的每个键设置导航属性?

    并且,我可以在对象的同一主键上没有多个外键吗?

    更新

    因此,要定义关系,您是否使用ClassName.PrimaryKeyProperty?或者你使用导航属性?或两者?混淆!!

    更新2

    所以为了建立关系,你必须定义双方......我想。

    Public Class Customer
        Public Property ID AS Integer
        Public Overrideable Property Locations AS ICollection(OF CustomerLocation)
    
    End Class
    
    Public Class CustomerLocation
        Public Property ID AS Integer
        Public Property CustomerID AS Integer
    
    End Class
    

2 个答案:

答案 0 :(得分:97)

当您有多个级联删除路径时,这是由SQL Server引起的异常。如果删除PaymentTerm,它将触发所有三个关系的级联删除。创建SalesOrderInvoice时会出现这种情况。 EF默认情况下会创建与ON DELETE CASCADE的所有一对多关系,您可以将您的特定关系重新映射为不使用它:

modelBuilder.Entity<...>()
            .HasRequired(...)
            .WithMany(...)
            .HasForeignKey(...)
            .WillCascadeOnDelete(false);

或者你可以通过删除惯例将其全局关闭:

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();   

您可以通过使用如下所示的行编辑生成的Up()方法来解决特定迁移上的此错误:

AddForeignKey("dbo.Payments", "EventID", "dbo.Events", "EventID", cascadeDelete: true)

并在违规关系上将cascadeDelete:值更改为false。

答案 1 :(得分:4)

阅读this,我相信这有助于您找到答案。

另外,根据ScottGu的blogpost,我认为一般情况下你应该按照以下方式创建类(我没有仔细阅读它,所以你应该查看它以获取更多细节):

public class Customer
{
    public int CustomerID { get; set; }
    public int CustomerLocationID { get; set; }
    public virtual CustomerLocation Location { get; set; }
}

public class CustomerLocation
{
    public int CustomerLocationID { get; set; }
    public virtual ICollection<Customer> Customers { get; set; }
}