Entity Framework Code First - 为不同的目的映射同一个实体两次
Entity Framework Code First - map same entity twice for different purpose
我有两个模型,一个 ApplicationUser
包含系统中的所有用户,我有一个 Quotation 模型包含所有 Quotations
所做的。现在我想在 Quotations
内存储两个到 ApplicationUser
的映射。这样我就可以映射到创建的用户以及取消的用户。我的模型看起来像这样
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'.
所以我猜想,我采用的方法是错误的。谁能指出实现此目标的正确方法?
您正在观察的问题叫做 "Multiple Cascade Path"。当级联路径从 table A 中的列 col1 到 table B 以及从 table A 中的列 col2 到 table B.
异常是由 SQL 服务器引起的,当时代码首次尝试添加 table,其中的列多次出现在另一个 table。
在 SQL 服务器中,table 在由 DELETE 或 UPDATE 语句启动的所有级联引用操作的列表中不能出现超过一次。例如,级联引用操作树必须只有一条路径指向级联引用操作树上的特定 table。
您将需要使用 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; }
}
现在在你的上下文中 class 你可以写:
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。
我有两个模型,一个 ApplicationUser
包含系统中的所有用户,我有一个 Quotation 模型包含所有 Quotations
所做的。现在我想在 Quotations
内存储两个到 ApplicationUser
的映射。这样我就可以映射到创建的用户以及取消的用户。我的模型看起来像这样
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'.
所以我猜想,我采用的方法是错误的。谁能指出实现此目标的正确方法?
您正在观察的问题叫做 "Multiple Cascade Path"。当级联路径从 table A 中的列 col1 到 table B 以及从 table A 中的列 col2 到 table B.
异常是由 SQL 服务器引起的,当时代码首次尝试添加 table,其中的列多次出现在另一个 table。
在 SQL 服务器中,table 在由 DELETE 或 UPDATE 语句启动的所有级联引用操作的列表中不能出现超过一次。例如,级联引用操作树必须只有一条路径指向级联引用操作树上的特定 table。
您将需要使用 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; }
}
现在在你的上下文中 class 你可以写:
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。