【问题标题】:How to create view model without sorting collections in memory如何在不对内存中的集合进行排序的情况下创建视图模型
【发布时间】:2011-01-13 22:04:24
【问题描述】:

我有一个视图模型(如下)。

public class TopicsViewModel
{
    public Topic Topic { get; set; }
    public Reply LastReply { get; set; }
}

我想用我的IQueryable<Topic> 集合和IQueryable<Reply> 集合中的值填充IQueryable<TopicsViewModel>。我不想使用附加的实体集合(即 Topic.Replies),因为我只想要该主题的最后一个回复,并且执行 Topic.Replies.Last() 将整个实体集合加载到内存中,然后抓取最后一个列表。我试图留在 IQueryable 中,以便在数据库中执行查询。

我也不想遍历主题并查询replyRepository.Replies,因为循环通过IQueryable<Topic> 将启动延迟加载。我更喜欢构建一个表达式,并在较低层完成所有腿部工作。

我有以下几点:

IQueryable<TopicsViewModel> topicsViewModel = from x in topicRepository.Topics
                                              from y in replyRepository.Replies
                                              where y.TopicID == x.TopicID
                                              orderby y.PostedDate ascending
                                              select new TopicsViewModel { Topic = x, LastReply = y };

但这不起作用。有什么想法可以填充 TopicsViewModel 的 IQueryable 或 IEnumerable 以便它查询数据库并获取主题和该主题的最后回复?我正在努力避免获取与该主题相关的所有回复。我只想抢最后的回复。

感谢您提供的任何见解。

【问题讨论】:

  • 主题和回复之间是否有导航属性?
  • 是的,这就是我所说的附加实体集合。但是,我不想访问该导航属性并触发整个集合的延迟加载。如果我需要该集合中的所有项目,那将是有意义的,但由于我只需要该集合中的最后一项,因此最好以某种方式保留在 IQueryable 中。
  • 当您说“不工作”时,究竟是哪一部分不工作?运行时异常,什么都没有返回,或者什么都返回了..?

标签: c# linq entity-framework linq-to-entities


【解决方案1】:

由于没有人回答,我现在使用 foreach 解决方案。我认为遍历最终将被延迟加载的主题比填充回复集合要好得多,这样我就可以访问集合中的最后一个对象。

这是我现在所做的:

                List<TopicsViewModel> topicsViewModelList = new List<TopicsViewModel>();
                foreach (Topic topic in topics)
                {
                    Reply lastReply = replyRepository.GetRepliesBy_TopicID(topic.TopicID).OrderBy(x => x.PostedDate).LastOrDefault();

                    topicsViewModelList.Add(new TopicsViewModel
                    {
                        Topic = topic,
                        LastReply = lastReply
                    });
                }

我只是先加载我的IQueryable&lt;Topics&gt;,然后循环遍历最终结果(以确保在循环之前完成数据的正确分页)并加载最后一个回复。这似乎避免了填充回复集合,而是只获取每个主题的最后一个回复。

【讨论】:

  • 不需要实例化topicsViewModelList吗?
【解决方案2】:
        from r in replies
        group r by new { r.TopicId } into g
        select new
            {
                TopicId = g.Key.TopicId, 
                LastReply = g.Max(p => p.PostedDate)
            }

【讨论】:

  • 没关系。任何查询导航属性实体集合的尝试都会触发整个集合的延迟加载。然后 LINQ 执行 .First() 或 .Last() 工作正常,但在幕后整个集合被加载到内存中,然后我们抓取集合中的第一个或最后一个对象。
  • 是的。所以,也许你在这里唯一的选择就是使用 .Max() 函数。
  • 找到了一个结合 SelectMany 和 .Max() 的好例子。 stackoverflow.com/questions/2462261/…
  • 该代码示例将填充一个 TopicsViewModel 对象,而不是 IQueryable&lt;TopicsViewModel&gt;
猜你喜欢
  • 2016-12-05
  • 1970-01-01
  • 1970-01-01
  • 2021-08-17
  • 1970-01-01
  • 1970-01-01
  • 2011-11-06
  • 2013-07-27
  • 1970-01-01
相关资源
最近更新 更多