我首先使用实体框架 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 列,这是为什么呢?