【问题标题】:NHibernate parent list with child countNHibernate 父列表与子计数
【发布时间】:2017-05-28 20:04:53
【问题描述】:

我正在使用 NHibernate 4 和 mysql。我有 2 张桌子。我的桌子是猫和答案。

public class cat
{
    [Key]
    public virtual int id { get; set; }
    public virtual string catName { get; set; }

    public virtual IList<answer> answers { get; set; }
}

public class answer
{
    [Key]
    public virtual int id { get; set; }
    public virtual int catId { get; set; }
    public virtual string detail { get; set; }
    public virtual bool stat { get; set; }

    [ForeignKey("catId")]
    public virtual cat cats { get; set; }
}

我想选择所有猫记录(带有答案列表)和它们的 cild 答案计数。

我的 sql 查询是这样的;

select count(t2.id) as count, cats.*from cat cats left join answer t2 ON(cats.id=t2.catId and t2.stat=0) GROUP BY(cats.id);

这样的结果;

id - catName - 计数

1 - 书 - 5

2 - 个人电脑 - 0

3 - 英语 - 22

4 - 艺术 - 56

我也尝试过这个 NH 查询;

public class myClass {
  public virtual int count { get; set; }
  public virtual cat cats { get; set; }
}

var u = db.CreateCriteria(typeof(cat), "cats")
       .CreateAlias("answer", "t2", NHibernate.SqlCommand.JoinType.LeftOuterJoin, Restrictions.Eq("t2.stat", false))
      .SetProjection(Projections.ProjectionList()
      .Add(Projections.Count("t2.id"), "count")
      .Add(Projections.Group<cat>(g => g.id)));


var list = u.SetFetchMode("answer", FetchMode.Eager)
        .SetResultTransformer(Transformers.AliasToBean<myClass>())
        .List<myClass>();

这个 NHibernate 查询返回也回答了计数。但是猫总是返回null。我该如何查询这个结果?

编辑 1 我可以这样做

public class myClass {
  public virtual int count { get; set; }
  public virtual catId count { get; set; }
  public virtual cat cats { get; set; }
}


cat cats = null;
answer answers = null;

var u = db.QueryOver<cat>(() => cats)
    .JoinQueryOver(x => x.answers, () => answers, NHibernate.SqlCommand.JoinType.LeftOuterJoin, Restrictions.Eq("answers.stat", false))
    .SelectList(cv => cv
        .SelectCount(() => answers.id)
        .SelectGroup(c => c.id))
    .List<object[]>()
    .Select(ax => new myClass
    {
      count = (int)ax[0],
      catId = (int)ax[1],
      cats = (cat)db.QueryOver<cat>().Where(w=>w.id==(int)ax[1]).Fetch(fe => fe.answers).Eager.SingleOrDefault()
    })
    .ToList();

【问题讨论】:

  • 小题外提示:如果你有选择,摆脱条件 api 并使用来自 NHibernate 的QueryOver or Query Api

标签: c# mysql nhibernate fluent-nhibernate sql-to-linq-conversion


【解决方案1】:

在您的结果中,cats 始终为 null,因为 ResultTransformer 尝试通过名称映射属性。

请检查您的 NHibernate 日志文件。您可能会看到您的查询返回列 countid,但 myClass 具有属性 countcats

编辑:

新建议:

前面的建议不起作用,因为属性id 的类型为Int32,不能分配给myClass.cat(类型为cat)。

如果您不需要引用myClass 中的cat-object,那么您可以将其更改为:

public class myClass {
  public virtual int count { get; set; }
  public virtual int catId { get; set; }
}

并有这样的投影:

.Add(Projections.Group<cat>(g => g.id), "catId"));

如果您在结果类中确实需要 cat 类型的属性,我认为这不能通过简单的投影来完成,但我可能错了。

编辑 2:

由于您在结果中需要cat 类型的对象,我建议您在查询后手动将其放在一起,例如:

新结果类:

public class myClassResult {
  public virtual int count { get; set; }
  public virtual cat cats { get; set; }
}

在查询逻辑之后添加:

IList<myClassResult> result = new List<myClassResult>();
foreach (var idWithCount in list) 
{
  result.Add(new myClassResult() 
  {
    cats = catsOnlyList.FirstOrDefault(x => x.id == idWithCount.catId),
    count = idWithCount.count
  });
}

catsOnlyList 指的是你需要事先得到的一个简单的猫列表。我知道这并不漂亮,但我认为您不能在查询中按 cat 本身分组。

旧建议(由于类型不兼容而不起作用):

代替

.Add(Projections.Group<cat>(g => g.id)));

使用

.Add(Projections.Group<cat>(g => g.id), "cats"));

【讨论】:

  • Florian Lim 返回相同的列。给出这个错误: System.Int32 类型不能分配给 cat 类型的属性
  • @ASPMaker 抱歉,我没有测试解决方案。我应该知道这不起作用,因为按 ID 分组不会得到cat 类型的结果属性。我修改了答案。
  • 我很抱歉,但这个更改只给了我 id。我想要这个查询,它必须返回答案计数和带有答案子级的 cat 表。我在我的问题中解释了所有这些。
  • @ASPMaker 在这种情况下,您将不得不手动将结果放在一起。请参阅我的第二次编辑。
【解决方案2】:

我可以这样查询;

public class myClass {
  public virtual int count { get; set; }
  public virtual İnt catId { get; set; }
  public virtual cat cats { get; set; }
}

cat cats = null;
answer answers = null;

var u = db.QueryOver<cat>(() => cats)
    .JoinQueryOver(x => x.answers, () => answers, NHibernate.SqlCommand.JoinType.LeftOuterJoin, Restrictions.Eq("answers.stat", false))
    .SelectList(cv => cv
        .SelectCount(() => answers.id)
        .SelectGroup(c => c.id))
    .List<object[]>()
    .Select(ax => new myClass
    {
      count = (int)ax[0],
      catId = (int)ax[1],
      cats = (cat)db.QueryOver<cat>().Where(w=>w.id==(int)ax[1]).Fetch(fe=>fe.answers).Eager.SingleOrDefault()
    })
    .ToList();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多