4

我有以下类定义

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 }
}

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

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>

IndepdendentClass 应该填充它们的 Impl2,前两个 Impl1 应该填充 IndependentClass。

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

4

3 回答 3

2

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

  • AbstractClass.IndependentClass<->IndependentClass.(NoNavigationProperty)
  • IndependentClass.Impl1<->Impl1.(NoNavigationProperty)
  • IndependentClass.Impl2s<->Impl2.(NoNavigationProperty)

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

IndepdendentClasses 应该填充它们的 Impl2s,前两个 Impl1s 应该填充 IndependentClasses

...因为您没有填充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<AbstractClass>在您的上下文类中没有a,那么上述两种关系是可能的。对于 EF,您的模型没有任何继承,而是将Impl1(and Impl2) 视为一个仅包含其自身属性和基类属性的实体,就好像它是一个没有基类的类一样。

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

于 2012-07-22T20:52:44.510 回答
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 做任何改变。

于 2012-07-22T18:38:58.933 回答
0

You need to initialize the properties in your constructor.

EF will only do that for you if the instances come from an EF DataContext.

When you write new Impl2(), EF is not involved at all.

于 2012-07-22T17:29:17.027 回答