C# 实体框架-虚拟属性为空

C# 实体框架-虚拟属性为空,c#,entity-framework,C#,Entity Framework,我有以下的类定义 public abstract class AbstractClass { [Key] public string Name { get; set; } public virtual IndependentClass IndependentClass { get; set; } public string IndependentClassName { get { return IndependentClass == null ? "<N

我有以下的类定义

public abstract class AbstractClass
{

    [Key]
    public string Name { get; set; }
    public virtual IndependentClass IndependentClass { get; set; }

    public string IndependentClassName { get { return IndependentClass == null ? "<NULL>" : IndependentClass.Name; } }
}

public class Impl1 : AbstractClass
{
}

public class Impl2 : AbstractClass
{
}

public class IndependentClass
{
    [Key]
    public string Name { get; set; }

    public virtual Impl1 Impl1 { get; set; }
    public virtual ICollection<Impl2> Impl2s { get; set; }
}
我的初始化如下所示(将数组添加到上下文和
context.SaveChanges()
trimmed)

最后,我有一个简单的视图转储每个db集合。我的问题是导航属性没有像我需要的那样被填充。i、 例如,我的观点的输出是:

Independent Classes:

    A: Impl1 = a, Impl2s = []
    B: Impl1 = b, Impl2s = []

Impl1s

    a: IndependentClass = <NULL>
    b: IndependentClass = <NULL>
    c: IndependentClass = <NULL>

Impl2s

    a1: IndependentClass = A
    a2: IndependentClass = A
    b1: IndependentClass = B
    b2: IndependentClass = B
    c1: IndependentClass = <NULL>
独立类:
A:Impl1=A,Impl2s=[]
B:Impl1=B,Impl2s=[]
IMP1S
a:独立类=
b:独立类=
c:独立类=
Impl2s
a1:独立类=A
a2:独立类=A
b1:独立类=B
b2:独立类=B
c1:独立类=
IndependentClass应填充其IMPL2,前两个IMPL1应填充IndependentClass


谁能告诉我我做错了什么吗?

您需要初始化构造函数中的属性

只有当实例来自EF DataContext时,EF才会为您这样做


当您编写
newimpl2()
时,根本不涉及EF。

显然,解决方案是替换

modelBuilder.Entity<AbstractClass>().HasOptional(abs => abs.IndependentClass);
modelBuilder.Entity<IndependentClass>().HasRequired(ind => ind.Impl1);
modelBuilder.Entity<IndependentClass>().HasMany(ind => ind.Impl2s);
modelBuilder.Entity().HasOptional(abs=>abs.IndependentClass);
modelBuilder.Entity().HasRequired(ind=>ind.Impl1);
modelBuilder.Entity().HasMany(ind=>ind.Impl2s);

modelBuilder.Entity()
.has可选(abs=>abs.IndependentClass)
.WithRequired(ind=>ind.Impl1);

但我不确定为什么不必为Impl2更改任何内容。

您的模型与以下导航属性有三种关系:

  • AbstractClass.IndependentClass
    IndependentClass.(非活动属性)
  • IndependentClass.Impl1
    Impl1.(非活力属性)
  • IndependentClass.Impl2s
    Impl2.(非活力属性)
对于每个关系,关联的一端不作为导航属性公开。在这个模型中不期望

IndependentClass应该填充其impl2,并且 前两个impl1应该填充独立类

…因为您没有在初始化代码中填充
IndependentClass.Impl2s
,也没有填充
Impl1.IndependentClass
。您填写
Impl2.IndependentClass
,但由于此导航属性属于另一个关系,因此它根本不会影响
IndependentClass.Impl2s

如果你想要两段感情

  • IndependentClass.Impl1
    Impl1.IndependentClass
    (一对一)
  • IndependentClass.Impl2s
    Impl2.IndependentClass
    (一对多)
…只要您的
AbstractClass
是模型中具有自己表的实体,您就无法实现这一点,因为您必须在它们声明的类型的导航属性之间进行映射,和
Impl1.IndependentClass
Impl2.IndependentClass
是继承的属性,但它们未在
Impl1
Impl2
中声明

如果您没有将
AbstractClass
作为一个实体,即在映射代码时不使用此抽象类,并且在您的上下文类中没有
DbSet
,则上述两种关系是可能的。对于EF,您的模型没有任何继承,而是将
Impl1
(和
Impl2
)视为一个实体,它只包含自己的属性和基类的属性,就好像它是一个没有基类的类一样


这就是为什么您自己的答案中的映射会像您预期的那样工作:您已经使用Fluent API明确定义了
IndependentClass.Impl1
Impl1.IndependentClass
之间的一对一关系。
IndependentClass.Impl2s
Impl2.IndependentClass
之间的第二个关系是通过将约定命名为一对多关系自动检测的。

我的视图从数据上下文获取对象,因此这不是问题所在,因为此映射
AbstractClass
不再是实体(并且没有自己的表)与您问题中的映射相反。
Impl1.IndependentClass
Impl2.IndependentClass
现在是两个独立的导航属性(上面的
abs
Impl1
,而不是
AbstractClass
),一个是指上面的映射代码定义的
IndependentClass.Impl1
,另一个是指按照约定自动映射为一对多的
IndependentClass.Impl2s
。您的新模型有两个关系,旧模型有三个。Ohhhh,这很有意义。如果您用这个来回答问题,我会答对了。谢谢!我实际上已经开始写答案了,但当你自己的答案出现时,我就停了下来。幸运的是,我保存了一份草稿,所以我现在可以恢复并扩展一下。
Independent Classes:

    A: Impl1 = a, Impl2s = []
    B: Impl1 = b, Impl2s = []

Impl1s

    a: IndependentClass = <NULL>
    b: IndependentClass = <NULL>
    c: IndependentClass = <NULL>

Impl2s

    a1: IndependentClass = A
    a2: IndependentClass = A
    b1: IndependentClass = B
    b2: IndependentClass = B
    c1: IndependentClass = <NULL>
modelBuilder.Entity<AbstractClass>().HasOptional(abs => abs.IndependentClass);
modelBuilder.Entity<IndependentClass>().HasRequired(ind => ind.Impl1);
modelBuilder.Entity<IndependentClass>().HasMany(ind => ind.Impl2s);
modelBuilder.Entity<Impl1>()
    .HasOptional(abs => abs.IndependentClass)
    .WithRequired(ind => ind.Impl1);