我遇到了一个奇怪的问题,我需要一些帮助。我试图在EF Code First中做一个简单的一对多关系。我们的想法是让一个 CardCategory 有多个 CardQuery 实例。
以下是我对CardCategory的定义:
public abstract class CardCategory
{
[Key, DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int Number { get; set; }
[Required]
public string Title { get; set; }
[InverseProperty("Category")]
public virtual ICollection<CardQuery> DataQueries { get; set; }
public CardCategory()
{
// this ensures that the collection is never null (avoiding NullReferenceException).
// it's no problem, because the constructor gets called before
// data mapping occurs.
DataQueries = new List<CardQuery>();
}
}
这是CardQuery:
public abstract class CardQuery
{
[Key, DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int Number { get; set; }
[InverseProperty("DataQueries")]
public virtual CardCategory Category { get; set; }
}
奇怪的是,当我尝试使用我的数据样本(少数类别与少量查询相关联)时,只能单向运行。我可以像这样获取每个查询的父类:
var query = myContext.CardQueries.Find(1);
var category = query.Category; // this works alright
但是当我以相反的方式尝试这个时(为了获得一个类别的所有子查询),我得到的只是一个空集合。
var category = myContext.CardCategories.Find(1);
var queries = category.DataQueries; // here is the problem, I get null or empty collection
也许你想知道CardCategory构造函数中的安全线是否与此有关。 它没有,相信我。我尝试的第一件事是删除它,我得到的只是一个空而不是空集合。
具有讽刺意味的是,“DataQueries”导航属性的工作原理不同:
var query = myContext.CardQueries.Find(1);
var category = query.Category;
var queries = category.DataQueries; // this works, I don't know what's different
看起来EF似乎无法填充属性,但我找不到原因。这在我之前从未发生过,我有点困惑。我很感激任何建议。
最后要清除的是,我的数据上下文配置如下:
LazyLoadingEnabled = true;
ProxyCreationEnabled = true;
AutoDetectChangesEnabled = true;
感谢您的帮助!
答案 0 :(得分:1)
我不建议使用Include,它会导致严重的性能下降。
你的问题是DataQueries是一个数组,只是调用category.DataQueries不会对存储执行任何查询(就像你不能编写myContext.CardQueries并自动获得结果一样)。您需要明确地调用启动器,例如ToList()或FirstOrDefault()。
所以,不要使用.Include尝试这个:
var category = myContext.CardCategories.Find(1);
var queries = category.DataQueries.ToList();
这将启动枚举器,您将获得DataQueries的结果。
作为旁注:你甚至可以通过例如过滤你的category.DataQueries。使用Where语句。
答案 1 :(得分:0)
var category = myContext.CardCategories
.Include(e => e.DataQueries)
.Find(1);
答案 2 :(得分:0)
我有一个类似但无关的问题。我试图延迟加载一些嵌套对象,例如访问Foo.Bar.Baz我的问题是Baz从未延迟加载,即使Bar on Bar是虚拟的。
事实证明,这个问题是由Bar私人所致。将ctor更改为protected允许EF正确创建Bar的代理类并启用延迟加载Baz集合。