实体框架代码优先 - 为同一个实体两次映射相同的实体

时间:2015-02-24 05:22:07

标签: asp.net-mvc entity-framework ef-code-first code-first

我有两个模型,一个ApplicationUser,它包含系统中的所有用户,我有一个Quotation模型,可以保存所有Quotations。现在我想将两个映射存储到ApplicationUser内的Quotations。这样我就可以映射到创建用户以及取消用户。我的模型看起来像这样

    public class Quotation
{
    public int QuotationID { get; set; }
    public DateTime QuotationDate { get; set; }
    public DateTime QuotationCancelDate { get; set; }
    public int ApplicationUserID { get; set; }
    public virtual ApplicationUser CreatedUser { get; set; }
    [ForeignKey("ApplicationUserID")]
    public ApplicationUser CancelledUser { get; set; }

}

但这会引发错误

Quotation_CancelledUser_Target_Quotation_CancelledUser_Source: : The types of all properties in the Dependent Role of a referential constraint must be the same as the corresponding property types in the Principal Role. The type of property 'ApplicationUserID' on entity 'Quotation' does not match the type of property 'Id' on entity 'ApplicationUser' in the referential constraint 'Quotation_CancelledUser'.

所以我猜,我采取的方法是错误的。任何人都可以指出实现这一目标的正确方法吗?

1 个答案:

答案 0 :(得分:1)

您正在观察的问题被称为" Multiple Cascade Path"。当级联路径从表A中的列col1到表B以及从表A中的列col2到表B时,会发生多个级联路径。

当代码首次尝试添加具有多次出现在另一个表中的列的表时,SQL Server会导致异常。

在SQL Server中,表不能在DELETE或UPDATE语句启动的所有级联引用操作的列表中出现多次。例如,级联引用操作树必须只有一条到级联引用操作树上特定表的路径。

您需要使用FluentAPI来配置关系。我目前正在使用EF5,不知道这是否可以在EF6 / 7中完成。

所以修改你的代码示例,它看起来像:

public class Quotation
{
    public int QuotationID { get; set; }
    public DateTime QuotationDate { get; set; }
    public DateTime QuotationCancelDate { get; set; }

    public int CreatedUserID { get; set; }
    // Navigation property
    public virtual ApplicationUser CreatedUser { get; set; }

    public int CancelledUserID { get; set; }
    // Navigation property
    public virtual ApplicationUser CancelledUser { get; set; }
}

// Created a simple class for example
public class ApplicationUser
{
    [Key]
    public int Id { get; set; }

    public string Name { get; set; }
}

现在在你的上下文课中你可以写:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //  Disable the default PluralizingTableNameConvention
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

        // Add configuration here

        modelBuilder.Entity<Quotation>()
            .HasKey(e => e.QuotationID);

        modelBuilder.Entity<ApplicationUser>()
            .HasKey(e => e.Id);

        modelBuilder.Entity<Quotation>()
                        .HasRequired(a => a.CreatedUser)
                        .WithMany()
                        .HasForeignKey(u => u.CreatedUserID);

        modelBuilder.Entity<Quotation>()
            .HasRequired(a => a.CancelledUser)
            .WithMany()
            .HasForeignKey(u => u.CancelledUserID);
    }

有关示例的更多信息,请参阅此link