实体框架 - 虚拟属性为空

时间:2012-07-22 17:26:45

标签: 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 ? "<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.OnModelCreating

中使用这些内容
modelBuilder.Entity<AbstractClass>().HasOptional(abs => abs.IndependentClass);
modelBuilder.Entity<IndependentClass>().HasRequired(ind => ind.Impl1);
modelBuilder.Entity<IndependentClass>().HasMany(ind => ind.Impl2s);

我的初始化看起来像这样(将数组添加到上下文并context.SaveChanges()修剪)

var impl1s = new[]
{
    new Impl1() { Name = "a" },
    new Impl1() { Name = "b" },
    new Impl1() { Name = "c" }
}

var inds = new[]
{
    new IndependentClass() { Name = "A", Impl1 = impl1s[0] },
    new IndependentClass() { Name = "B", Impl1 = impl1s[1] }
}

var impl2s = new[]
{
    new Impl2() { Name = "a1", IndependentClass = inds[0] },
    new Impl2() { Name = "a2", IndependentClass = inds[0] },
    new Impl2() { Name = "b1", IndependentClass = inds[1] },
    new Impl2() { Name = "b2", IndependentClass = inds[1] },
    new Impl2() { Name = "c1", IndependentClass = null }
}

最后我有一个简单的View转储每个db集合。我的问题是导航属性没有像我需要的那样填充。即,我的观点的输出是这样的:

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>

IndepdendentClasses应填充其Impl2,前两个Impl1应填充IndependentClasses。

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

3 个答案:

答案 0 :(得分:2)

显然解决方案是替换

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

但我不确定为什么我不必为Impl2改变任何东西。

答案 1 :(得分:1)

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

  • AbstractClass.IndependentClass&lt; - &gt; IndependentClass.(NoNavigationProperty)
  • IndependentClass.Impl1&lt; - &gt; Impl1.(NoNavigationProperty)
  • IndependentClass.Impl2s&lt; - &gt; Impl2.(NoNavigationProperty)

对于每个关系,关联的一端不会作为导航属性公开。在这个模型中没有预期......

  

IndepdendentClasses应填充其Impl2,并且   前两个Impl1应该填充IndependentClasses

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

如果你真的想要两个关系......

  • IndependentClass.Impl1&lt; - &gt; Impl1.IndependentClass(一对一)
  • IndependentClass.Impl2s&lt; - &gt; Impl2.IndependentClass(一对多)

...只要您的AbstractClass是模型中具有自己的表的实体,就无法实现这一点,因为您必须在声明的类型的导航属性之间进行映射 in,Impl1.IndependentClassImpl2.IndependentClass是继承的属性,但未在Impl1Impl2中声明。

如果你没有使AbstractClass成为一个实体,即不在映射代码中使用这个抽象类而在你的上下文类中没有DbSet<AbstractClass>,那么上面的两个关系是可能。对于EF,您的模型没有任何继承,而是将Impl1(和Impl2)视为仅包含其自己的属性以及基类的属性的实体,就好像这是一个没有基础的班级。

这就是为什么您自己的答案中的映射按预期工作的原因:您已使用Fluent API明确定义了IndependentClass.Impl1Impl1.IndependentClass之间的一对一关系。 IndependentClass.Impl2sImpl2.IndependentClass之间的第二个关系通过命名约定自动检测为一对多关系。

答案 2 :(得分:0)

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

如果实例来自EF DataContext,EF只会为您执行此操作。

当您写new Impl2()时,EF根本不参与。