1

我首先使用实体​​框架 4.3 代码来持久化域模型。领域模型由抽象类和具体类组成。当实体框架返回的具体类首次尝试访问基类中的对象集合时,我看到抛出 ArgumentNullException。

例如,域模型由抽象类组成

public abstract class Foo
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Attibute> attributes { get; set; }

    public string DoSomething()
    {
        return "I'm all fooey";
    }
}

public abstract class Attibute
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Foo> Foos { get; set; }
}

然后我有派生类

public class BadFoo : Foo
{
    public List<BadAttribute> BadAttribs()
    {
        return base.attributes.OfType<BadAttribute>().ToList<BadAttribute>();
    }

    public void BeBad()
    {
        foreach (var a in BadAttribs())
            Console.WriteLine(Name + ": Being bad => " + a.DoingBad());
    }
}

public class GoodFoo : Foo
{
    public List<GoodAttribute> GoodAttribs()
    {
        return base.attributes.OfType<GoodAttribute>().ToList<GoodAttribute>();
    }

    public void BeGood()
    {
       foreach (var a in GoodAttribs())
            Console.WriteLine(Name + ": Being good => " + a.DoingGood());
    }
}


public class BadAttribute : Attibute
{
    public string DoingBad()
    {
        return Name + " : Start being bad";
    }
}

public class GoodAttribute : Attibute
{
    public string DoingGood()
    {
        return Name + " : Start being Good";
    }
}

public class AppearenceAttribute : Attibute
{
    public string Doing()
    {
        return Name + " : defining ones appearance";
    }
}

然后我设置我的数据库上下文如下:

public class EFDbContext : DbContext
{
    public DbSet<Foo> Foos { get; set; }
    public DbSet<Attibute> Attributes { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    }
}

public class EFDbContextInitializer : DropCreateDatabaseAlways<EFDbContext> 
{
    protected override void Seed(EFDbContext context)
    {
        List<Attibute> attribs = new List<Attibute>
            {
                new BadAttribute { Name = "Gluttony" },
                new BadAttribute { Name = "Greed" },
                new GoodAttribute { Name = "Honesty" },
                new GoodAttribute { Name = "Humility" },
                new AppearenceAttribute { Name = "Colour" }
            };
        attribs.ForEach(a => context.Attributes.Add(a));
        context.SaveChanges();

        BadFoo badOne = new BadFoo { Name = "badOne", attributes = new List<Attibute>)};

        context.Attributes.OfType<BadAttribute>().ToList().ForEach(a => badOne.attributes.Add(a));
        context.Attributes.OfType<AppearenceAttribute>().ToList().ForEach(a => badOne.attributes.Add(a));

        context.Foos.Add(badOne);
        context.SaveChanges();

        GoodFoo goodOne = new GoodFoo { Name = "GoodOne", attributes = new List<Attibute>() };

        context.Attributes.OfType<GoodAttribute>().ToList().ForEach(a => goodOne.attributes.Add(a));
        context.Attributes.OfType<AppearenceAttribute>().ToList().ForEach(a => goodOne.attributes.Add(a));

        context.Foos.Add(goodOne);
        context.SaveChanges();

        base.Seed(context);
    }
}

然后我使用我的模型如下:

       Database.SetInitializer<EFDbContext>(new EFDbContextInitializer());

        EFDbContext context = new EFDbContext();

        var foos = context.Foos.OfType<BadFoo>().ToList();
        foreach (var f in foos)
            f.BeBad();

        var foos2 = context.Foos.OfType<GoodFoo>().ToList();
        foreach (var f in foos2)
            f.BeGood();

        Console.ReadKey();

当派生自 Foo 的具体类首次尝试使用 Foo 基类中的集合时,将引发异常。在这种情况下,BadFoo 实例第一次调用 BeBad() 方法。

我不确定是否是因为 EF 延迟加载集合,C# 处理抽象/具体类的方式或域模型只是让任何人愿意解释/启发我解决问题?

作为旁注,如果我将派生属性类 BadFoo 和 GoodFoo 中访问基属性的方式替换为返回基类集合属性的类型过滤列表的属性,例如:

public class GoodFoo : Foo
{
    public List<GoodAttribute> GoodAttribs()
    {
        return base.attributes.OfType<GoodAttribute>().ToList<GoodAttribute>();
    }
}

EF 在表中添加了一个 _Id 列,这是为什么呢?

4

1 回答 1

0

EF 代码首先根据配置和上下文定义构建 db 模型元数据。您已将 EF 设置为使用抽象 Foo 和 Attribute 类作为实体。所以它试图使用它。

public class EFDbContext : DbContext
{
    public DbSet<Foo> Foos { get; set; }
    public DbSet<Attibute> Attributes { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    }
}

它对您的后代类一无所知,也不知道如何映射它们。在我看来,您不能将抽象类用作实体,因为它没有任何意义。

在任何情况下,您的 Foo 和 Attibute 类本质上都不是抽象类。他们没有任何抽象方法。我建议您阅读更多关于 C# 中的抽象类或抽象关键字的信息。

于 2013-11-21T08:52:55.113 回答