EF 4.1代码优先:如何选择具有collection-property计数的实体

时间:2011-09-26 18:42:52

标签: lambda entity-framework-4.1 ef-code-first code-first navigation-properties

我有一个名为 Tag 的实体,其导航属性(集合)名为 Articles Tag 有一个名为 ArticleCount 的已忽略属性,用于保存相关的 Article s count(仅在运行时和在视图中使用 - 忽略DB)。参见:

public class Tag{

    public int Id { get; set; }

    public int Title { get; set; }

    public virtual ICollection<Article> Articles { get; set; }

    [NotMapped]
    public int ArticleCount { get; set; }

}

如何在 ONE 查询中使用 Tag 选择所有 ArticleCount (或其中一个) dataBase -in 实体框架4.1代码优先,使用lambda表达式,请?

2 个答案:

答案 0 :(得分:2)

var tagsAndCounts =  from tag in context.Tags
                     where ...
                     select new { tag, count = tag.Articles.Count() }
var tagsWithCount = tagsAndCounts.ToList()
                                 .Select(x => 
                                         {
                                             x.tag.ArticleCount = x.count;
                                             return x.tag;
                                         };

(我的设计方式不同 - ArticleCount不应该是模型的一部分,或者它应该是Articles上的投影,您可以使用Include()急切加载。这样做你想要的)


更新:我的设计。

public class Tag
{
   ...
   public int ArticleCount { get { return Articles.Count; } }
}

var tagsWithEagerLoadedArticles = context.Tags.Include(x => x.Articles)
                                         .Where(...).Etc();

当然,这是否表现良好取决于每个标签的预期文章数量。如果它是几十个,这将合理地工作,同时比其他方法更清洁。如果它是数百,另一个更好。

现在,如果是这种情况,您应该使用匿名或命名的演示文稿类型,而不是重用该实体。

答案 1 :(得分:1)

所有标记的示例:

var result = context.Tags
    .Select(t => new
    {
        Tag = t,
        ArticleCount = t.Articles.Count()
    });

foreach (var a in result)
    a.Tag.ArticleCount = a.ArticleCount;

var tags = result.Select(a => a.Tag).ToList();

这只是一个查询,副本发生在内存中。我相信除了将ArticleCount从匿名结果对象复制到标记之外别无他法,因为您无法直接投射到实体中,因此您无法使用Select(t => new Tag { ... });。您可以使用另一个命名的类型而不是匿名类型,但不能使用实体类型。