1

我有一个奇怪的问题,我需要一些帮助。我正在尝试在 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;

谢谢你的帮助!

4

3 回答 3

1

我不建议使用 Include,它会导致大型基地的性能严重下降。

您的问题是 DataQueries 是一个数组,只需调用 category.DataQueries 不会对存储执行任何查询(与您无法编写 myContext.CardQueries 并自动获取结果的方式相同)。您需要显式调用启动器,例如 ToList() 或 FirstOrDefault()。

所以,不要使用 .Include 试试这个:

var category = myContext.CardCategories.Find(1);
var queries = category.DataQueries.ToList();

这将启动枚举器,您将获得 DataQueries 的结果。

作为旁注:您甚至可以使用 Where 语句过滤您的 category.DataQueries。

于 2013-03-31T21:34:11.193 回答
1

我有一个类似但不相关的问题。我尝试延迟加载一些嵌套对象,例如访问 Foo.Bar.Baz 我的问题是 Baz 从未延迟加载,即使 Bar 上的 Collection 是虚拟的。

原来问题出在 Bar 的 ctor 上,是私有的。将 ctor 更改为 protected 允许 EF 正确创建 Bar 的代理类并启用 Baz 集合的延迟加载。

于 2015-07-31T11:53:02.770 回答
0

尝试使用IQueryable<T>.Include()

var category = myContext.CardCategories
    .Include(e => e.DataQueries)
    .Find(1);
于 2013-03-31T12:21:32.420 回答