c# - NHibernate 每组前 N 行

标签 c# nhibernate queryover

这是我的域名:

public class ForumTheme
{
    public virtual String Name { get;set; }
}

public class ForumTopic
{
    public virtual IList<ForumTheme> Themes { get;set; }
}

public class ForumMessage
{
    public virtual IList<ForumTopic> Topics { get;set; }

    public virtual DateTime DatePosted { get; set; }
}

我想要得到的是:

论坛主题列表,其中包含每个论坛主题的前 5 条最新论坛消息

在 NHibernate 中可以做到这一点吗?

更新

这是另一种可能的情况。

域名

该域描述了典型的分层博客/新闻网站。

public class Channel
{
    public virtual Int32 Id { get; set; }
    public virtual String Name { get; set; }

    public virtual IList<Category> Categories { get; set; }
}

public class Category
{
    public virtual IList<Article> Articles { get; set; }
}

public class Article
{
    public virtual String Name { get; set; }
    public virtual DateTime PublishDate { get; set; }
    public virtual Boolean IsActive { get; set; }
}

因此,一个 channel 包含多个类别,一个类别包含多个文章。

我在这里想做的是抓取每个 channel 的前 N ​​篇文章(忽略它们来自不同类别的事实)。这些文章将显示在我的门户的登陆页面上。

在应用程序中,我使用 ViewModels,它仅保存实际数据库数据的子集。 这是我的复合 ViewModel

DTO

public class ChannelDto
{
    public Int32 Id { get; set; }

    public String Name { get; set; }

    public List<ArticleDto> Articles { get; set; }

    public class ArticleDto
    {
        public String Name { get; set; }
    }
}

获取 channel 的查询非常简单(我们只显示那些包含活跃文章的 channel ):

Category categoryAlias = null;
Article articleAlias = null;
ChannelDto.ArticleDto articleDtoAlias = null;

List<ChannelDto> channels = _session.QueryOver<Channel>()
                                    .Inner.JoinAlias(x => x.Categories, () => categoryAlias)
                                    .Inner.JoinAlias(x => categoryAlias.Articles, () => articleAlias)
                                    .Where(x => articleAlias.IsActive)
                                    .SelectList(list => list
                                        .Select(x => x.Id)
                                        .Select(x => x.Name)
                                    )
                                    .List<Object[]>
                                    .Select(x => new ChannelDto
                                    {
                                        Id = (Int32) x[0],
                                        Name = (String) x[1]
                                    })
                                    .ToList();

上面的查询为我提供了包含活跃文章的 channel 列表。现在我将获取文章本身:

foreach(var channel in channels)
{
    channel.Articles = _session.QueryOver<Channel>()
                               .Inner.JoinAlias(x => x.Categories, () => categoryAlias)
                               .Inner.JoinAlias(x => categoryAlias.Articles, () => articleAlias)
                               .Where(x => x.Id == channel.Id)
                               .OrderBy(x => articleAlias.PublishDate).Desc
                               .SelectList(list => list
                                   .Select(x => articleAlias.Name).WithAlias(() => articleDtoAlias.Name)
                               )
                               .Take(5)
                               .List<Object[]>
                               .Select(x => new ChannelDto.ArticleDto
                               {
                                   Name = (String) x[0]
                               })
                               .ToList();
}

但是上面的 2 个查询存在 SELECT + 1 问题。我觉得使用 future 我可以用更少的往返来做到这一点。我对 NHibernate 还不太熟悉。 是否有可能通过一次往返和水合 DTO 获得所有内容?在 QueryOver 中使用类似 ROW_NUMBER() OVER (PARTITION BY....) 的东西?我不想使用 HQL 或原始 SQL。

最佳答案

使用 2 个往返

var themes = session.Query<ForumTheme>().Select(t => new ThemeDto(t.Name)).List();

var topMessages = new List<IEnumerable<string>>(themse.Count);

foreach(var theme in themes)
{
    var query = from message in session.Query<ForumMessage>()
                from topic in message.Topics
                from t in topic.Themes
                where t.Name == theme.Name
                orderby message.DatePosted desc
                select message;
    topMessages.Add(query.Take(5).ToFuture());
}

for(int i = 0;i < topMessages.Count; i++)
{
    themes.TopMessages = topMessages[i].ToList();
}

return themes;

对于你的第二种情况

foreach(var channel in channels)
{
    channel.Articles = _session
        .QueryOver<Channel>()
        .Inner.JoinAlias(x => x.Categories, () => categoryAlias)
        .Inner.JoinAlias(x => categoryAlias.Articles, () => articleAlias)
        .Where(x => x.Id == channel.Id)
        .OrderBy(x => articleAlias.PublishDate).Desc
        .SelectList(list => list
            .Select(x => articleAlias.Name).WithAlias(() => articleDtoAlias.Name)
        )
        .TransformUsing(Transformers.AliasToBean<ChannelDto.ArticleDto>());
}

// execute all subqueries at once through iterating one
channels[0].Articles.Any();

关于c# - NHibernate 每组前 N 行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12747573/

相关文章:

c# - 如何将 Linq 与 CaSTLe ActiveRecord 一起使用

wcf - 将 WCF 与 Sharp 架构集成的问题

NHIbernate:投影所有属性的快捷方式?

c# - 无法转换类型 'UnityEngine.Component'

c# - 允许从接口(interface)转换为实现的通用约束

C#,将 Xml 序列化与 Nhibernate 混合使用时出现问题

c# - NHibernate QueryOver - 检索所有,并标记那些已经是 "selected"

c# - QueryOver 查询中的重要顺序

c# - 如何调试打印第三方可执行文件的流程

c# - 如何将 .NET 图像或字节数组转换为 Emgu.CV.Image<Emgu.CV.Structure.Bgr , byte >