我的数据库中有两个表。一个称为Users
,另一个称为Widgets
。 Widgets
表表示我的代码模型中的3个实体。其中一个实体Widget
是其他两个实体WidgetTypeA
和WidgetTypeB
的父类。 WidgetTypeA
和WidgetTypeB
都具有User实体的导航属性,该实体持久保存到数据库中的Users表。我无法让Code First为WidgetTypeA
和WidgetTypeB
实体(UserId
)使用相同的外键。有谁知道如何做到这一点?看起来它应该是Table Per Hierarchy映射的常见问题。
我的实体类如下:
public class Widget
{
public int Id { get; set; }
public string Name { get; set; }
}
class WidgetMap : EntityTypeConfiguration<Widget>
{
public WidgetMap()
{
ToTable("Widgets");
HasKey(w => w.Id);
Property(w => w.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(w => w.Name)
.IsRequired()
.HasMaxLength(75)
.IsUnicode(true);
}
}
public class WidgetTypeA : Widget
{
public int UserId { get; set; }
public virtual User User { get; set; }
public string Color { get; set; }
public int DepthLevel { get; set; }
}
class WidgetTypeAMap : EntityTypeConfiguration<WidgetTypeA>
{
public WidgetTypeAMap()
{
Map(w => w.Requires("WidgetTypeId").HasValue(1));
HasRequired(w => w.User)
.WithMany(u => u.WidgetTypeAs)
.HasForeignKey(w => w.UserId)
.WillCascadeOnDelete(false);
Property(w => w.Color)
.IsOptional()
.IsUnicode(true)
.HasMaxLength(75);
Property(w => w.DepthLevel)
.IsOptional();
}
}
public class WidgetTypeB : Widget
{
public int UserId { get; set; }
public virtual User User { get; set; }
}
class WidgetTypeBMap : EntityTypeConfiguration<WidgetTypeB>
{
public WidgetTypeBMap()
{
Map(w => w.Requires("WidgetTypeId").HasValue(2));
HasRequired(w => w.User)
.WithMany(u => u.WidgetTypeBs)
.HasForeignKey(w => w.UserId)
.WillCascadeOnDelete(false);
}
}
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public int Age { get; set; }
public virtual ICollection<WidgetTypeA> WidgetTypeAs { get; set; }
public virtual ICollection<WidgetTypeB> WidgetTypeBs { get; set; }
}
class UserMap : EntityTypeConfiguration<User>
{
public UserMap()
{
ToTable("Users");
HasKey(u => u.Id);
Property(u => u.Username)
.IsRequired()
.HasMaxLength(75)
.IsUnicode(true);
Property(u => u.Age)
.IsRequired();
}
}
无论如何,我不断收到错误
无效的列名称'UserId1'
当我尝试执行以下操作时:
using (var entities = new MyEntities())
{
User u = new User
{
Username = "Frank",
Age = 14
};
entities.Users.Add(u);
entities.SaveChanges();
WidgetTypeA wa1 = new WidgetTypeA
{
Name = "0SDF81",
UserId = u.Id,
DepthLevel = 6
};
entities.WidgetTypeAs.Add(wa1);
entities.SaveChanges();
}
不确定是否可以修复此问题。我总是可以为Widgets表指定第二个UserId外键,但这似乎毫无意义。也许有一种方法可以使用Fluent API吗?
答案 0 :(得分:2)
您无法将在不同派生实体中定义的属性映射到同一列。这是EF的限制。如果您的WidgetTypeA
具有UserId
属性且您的WidgetTypeB
具有UserId
属性,则它们必须是数据库中的不同列。如果您将派生类型的UserId
和User
属性移动到父Widget
类型,它应该有效。
答案 1 :(得分:0)
我知道它已经很晚了,但希望可以帮助其他读者。
尽管Ladislav在EF6中不支持使用映射的外键,但我找到了一个有用的解决方法。
可以定义计算列规范,其表达式只是引用原始列。 Userid在上面的描述中。这可以用作TPH映射的鉴别器。使用这种方法,列不需要持久化,但可以用于TPH,原始列可用作外键。