Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 关于EF代码的困难首先是Fluent API、TPH和外键_C#_Entity Framework_Entity Framework 4.1_Ef Code First - Fatal编程技术网

C# 关于EF代码的困难首先是Fluent API、TPH和外键

C# 关于EF代码的困难首先是Fluent API、TPH和外键,c#,entity-framework,entity-framework-4.1,ef-code-first,C#,Entity Framework,Entity Framework 4.1,Ef Code First,我的数据库中有两个表。一个叫做Users,另一个叫做Widgets。Widgets表表示我的代码模型中的3个实体。其中一个实体,Widget,是其他两个实体,WidgetTypeA和WidgetTypeB的父类。WidgetTypeA和WidgetTypeB都具有指向用户实体的导航属性,该属性将持久化到数据库中的用户表中。我无法让代码首先为WidgetTypeA和WidgetTypeB实体(UserId)使用相同的外键。有人知道怎么做吗?这似乎是每个层次表映射的一个常见问题 我的实体类如下所示:

我的数据库中有两个表。一个叫做
Users
,另一个叫做
Widgets
Widgets
表表示我的代码模型中的3个实体。其中一个实体,
Widget
,是其他两个实体,
WidgetTypeA
WidgetTypeB
的父类。
WidgetTypeA
WidgetTypeB
都具有指向用户实体的导航属性,该属性将持久化到数据库中的用户表中。我无法让代码首先为WidgetTypeAWidgetTypeB实体(UserId)使用相同的外键。有人知道怎么做吗?这似乎是每个层次表映射的一个常见问题

我的实体类如下所示:

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

不确定这是否可以修复。我总是可以为Widgets表指定第二个UserId外键,但这似乎毫无意义。也许有一种方法可以使用Fluent API实现这一点?

您不能将不同派生实体中定义的属性映射到同一列。这就是EF的局限性。如果
WidgetTypeA
具有
UserId
属性,而
WidgetTypeB
具有
UserId
属性,则它们必须是数据库中的不同列。如果您将
UserId
User
属性从派生类型移动到父
Widget
类型,它应该会起作用。

我知道已经很晚了,但希望可以帮助其他读者

虽然Ladislav认为EF6不支持使用映射外键是正确的,但我确实找到了一个有用的解决方法

可以定义其表达式仅引用原始列的计算列规范。上面描述中的Userid。这可以用作TPH映射的鉴别器。使用这种方法,该列不需要持久化,但可以用于TPH,原始列可用作外键

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