繁体   English   中英

NHibernate投影失败

[英]NHibernate Projections failure

我有与文章类有多对多关系的标签类,问题是我想制作一个在标签视图模型类中表示的投影,所以列结果应该像这样

Id|Name|CreatedBy|CreatedDate|LastModifiedBy|LastModifiedDate|ArticlesCount

SQL查询应该是这样的:

 SELECT  t.*, COUNT(at.intTag) as ArticlesCount 
 FROM    dbo.TAG t
         LEFT OUTER JOIN dbo.ARTICLE_TAG at ON t.intID = at.intTag
         LEFT OUTER JOIN dbo.ARTICLE a ON at.intID = a.intID
 GROUP BY t.intID, t.vcName, t.intWeight, t.vcCreatedBy, t.dtCreated, t.vcLastMod, t.dtLastMod, t.btActive

但它说

  NHibernate.Exceptions.GenericADOException was caught
  HResult=-2146232832
  Message=could not execute query [ SELECT this_.intID as y0_, this_.vcName as y1_, this_.vcCreatedBy as y2_, this_.dtCreated as y3_, this_.vcLastMod as y4_, this_.dtLastMod as y5_, count(this_.intID) as y6_ FROM TB_TAG this_ WHERE this_.btActive = @p0 ]
  Name:cp0 - Value:True

这是我的Tag类:

public class Tag {
    public virtual string Name { get; set; }     
    public virtual int Weight { get; set; }
    public virtual IList<Article> Articles { get; set; }
    public virtual string CreatedBy { get; set; }
    public virtual DateTime CreatedDate { get; set; }
    public virtual string LastModifiedBy { get; set; }
    public virtual DateTime LastModifiedDate { get; set; }
    public virtual bool IsActive { get; set; }
}

这是映射类

internal sealed class TagMap : ClassMap<Tag>
{
    public TagMap()
    {
        Table("TB_TAG");

        Id(f => f.Id).Column("intID").GeneratedBy.Native();

        Map(f => f.Name).Column("vcName").Not.Nullable();
        Map(f => f.Weight).Column("intWeight").Not.Nullable();
        Map(f => f.IsActive).Column("btActive");
        Map(f => f.CreatedBy).Column("vcCreatedBy").Not.Update();
        Map(f => f.CreatedDate).Column("dtCreated").Not.Update();
        Map(f => f.LastModifiedBy).Column("vcLastMod");

        Version(f => f.LastModifiedDate).Column("dtLastMod");

        HasManyToMany(f => f.Articles).Table("S_ARTICLE_TAG")
                                      .ParentKeyColumn("intTag").ChildKeyColumn("intID")
                                      .Inverse();
    }

}

这是ViewModel类:

    public class TagView
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int ArticlesCount { get; set; }
        public virtual string CreatedBy { get; set; }
        public virtual DateTime CreatedDate { get; set; }
        public virtual string LastModifiedBy { get; set; }
        public virtual DateTime LastModifiedDate { get; set; }
        public virtual bool IsActive { get; set; }
    }

这是我的代码进行投影:

Tag t = null;
tags = _session.QueryOver(() => t)
               .Select(Projections.Id().As("Id"),
                       Projections.Property(() => t.Name).As("Name"),
                       Projections.Property(() => t.CreatedBy).As("CreatedBy"),
                       Projections.Property(() => t.CreatedDate).As("CreatedDate"),
                       Projections.Property(() => t.LastModifiedBy).As("LastModifiedBy"),
                       Projections.Property(() => t.LastModifiedDate).As("LastModifiedDate"),
                       Projections.Count(() => t.Articles).As("ArticlesCount"))
               .TransformUsing(Transformers.AliasToBean<TagView>())
               .List<TagView>();

这是我第一次使用投影,我不知道如何使它起作用。 我在这里想念什么吗?

您收到的错误表明NHibernate为投影生成的SQL无法以其当前形式执行。 查询正在

SELECT this_.intid        AS y0_, 
       this_.vcname       AS y1_, 
       this_.vccreatedby  AS y2_, 
       this_.dtcreated    AS y3_, 
       this_.vclastmod    AS y4_, 
       this_.dtlastmod    AS y5_, 
       Count(this_.intid) AS y6_ 
FROM   tb_tag this_ 
WHERE  this_.btactive = @p0 

这完全是由于count是一个聚合需要一个聚合函数这一事实。

您可以将“文章”集合标记为“懒惰”和“多余”,并在不加载整个集合的情况下获取“ Article.Count”值,如果这就是为什么要为其投影每列的原因。 有很多有效的文章可以指导您将某个收藏标记为特别懒惰

在阅读了NHIibernate API和此链接的答案后,终于找到了一种使之工作的方法。

这是我的最终代码:

Tag t= null;
TagView tv = null;
tags = _session.QueryOver(() => t)
               .Left.JoinQueryOver(() => t.Articles, () => a)
               .SelectList(list => list
                                       .SelectGroup(() => t.Id).WithAlias(() => tv.Id)
                                       .SelectGroup(() => t.Name).WithAlias(() => tv.Name)
                                       .SelectGroup(() => t.CreatedBy).WithAlias(() => tv.CreatedBy)
                                       .SelectGroup(() => t.CreatedDate).WithAlias(() => tv.CreatedDate)
                                       .SelectGroup(() => t.LastModifiedBy).WithAlias(() => tv.LastModifiedBy)
                                       .SelectGroup(() => t.LastModifiedDate).WithAlias(() => tv.LastModifiedDate)
                                       .SelectCount(() => t.Articles).WithAlias(() => tv.ArticlesCount))
               .TransformUsing(Transformers.AliasToBean<TagView>())
               .List<TagView>();

我需要使用.SelectList而不是.Select来投影列表,还要使nhibernate成功计数需要将其与相关表一起加入的文章,以在将类初始化标记文章映射为ExtraLazyLoad属性时也加快查询速度。 希望我也能帮助遇到同样问题的人。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM