NHibernate - 使用 ICriteria 加入子查询

发布于 2024-07-20 03:55:48 字数 1185 浏览 7 评论 0原文

我有一个 SQL 查询,需要使用 NHibernate 的 ICriteria API 来表示。

   SELECT u.Id as Id, 
    u.Login as Login, 
    u.FirstName as FirstName, 
    u.LastName as LastName, 
    gm.UserGroupId_FK as UserGroupId,
    inner.Data1,
    inner.Data2,
    inner.Data3
    FROM dbo.User u inner join 
    dbo.GroupMember gm on u.Id = gm.UserAnchorId_FK 
    left join
    (
        SELECT
        di.UserAnchorId_FK,
        sum(di.Data1) as Data1, 
        sum(di.Data2) as Data2, 
        sum(di.Data3) as Data3
        FROM
        dbo.DailyInfo di 
        WHERE di.Date between '2009-04-01' and '2009-06-01' 
        GROUP BY di.UserAnchorId_FK
    ) inner ON inner.UserAnchorId_FK = u.Id
    WHERE gm.UserGroupId_FK = 195 

到目前为止的尝试包括映射“User”和“DailyInfo”类(我的实体)并使 DailyInfo 对象成为 User 对象的属性。 然而,如何映射它们之间的外键关系仍然是一个谜,即

<one-to-one></one-to-one>

<one-to-many></one-to-many>

<generator class="foreign"><param name="property">Id</param></generator> (!) 

网络上的解决方案通常与 WHERE 子句中的子查询有关,但是我需要对此子查询进行左连接以确保行返回 NULL 值不加入的。

我觉得我应该对外部查询使用 Criteria,然后用 DetachedCriteria 形成“连接”来表示子查询?

I have a SQL query that I need to represent using NHibernate's ICriteria API.

   SELECT u.Id as Id, 
    u.Login as Login, 
    u.FirstName as FirstName, 
    u.LastName as LastName, 
    gm.UserGroupId_FK as UserGroupId,
    inner.Data1,
    inner.Data2,
    inner.Data3
    FROM dbo.User u inner join 
    dbo.GroupMember gm on u.Id = gm.UserAnchorId_FK 
    left join
    (
        SELECT
        di.UserAnchorId_FK,
        sum(di.Data1) as Data1, 
        sum(di.Data2) as Data2, 
        sum(di.Data3) as Data3
        FROM
        dbo.DailyInfo di 
        WHERE di.Date between '2009-04-01' and '2009-06-01' 
        GROUP BY di.UserAnchorId_FK
    ) inner ON inner.UserAnchorId_FK = u.Id
    WHERE gm.UserGroupId_FK = 195 

Attempts so far have included mapping 'User' and 'DailyInfo' classes (my entities) and making a DailyInfo object a property of the User object. However, how to map the foreign key relationship between them is still a mystery, ie

<one-to-one></one-to-one>

<one-to-many></one-to-many>

<generator class="foreign"><param name="property">Id</param></generator> (!) 

Solutions on the web are generally to do with subqueries within a WHERE clause, however I need to left join on this subquery instead to ensure NULL values are returned for rows that do not join.

I have the feeling that I should be using a Criteria for the outer query, then forming a 'join' with a DetachedCriteria to represent the subquery?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

烟雨凡馨 2024-07-27 03:55:48

我遇到了同样的问题,但没有得到任何解决方案。所以我

用 Criteria 生成的拦截器查询

SELECT u.Id as Id, 
u.Login as Login, 
u.FirstName as FirstName, 
u.LastName as LastName, 
gm.UserGroupId_FK as UserGroupId,
inner.Data1,
inner.Data2,
inner.Data3
FROM dbo.User u inner join 
dbo.GroupMember gm on u.Id = gm.UserAnchorId_FK 
InnerJoin inner ON inner.UserAnchorId_FK = u.Id
WHERE gm.UserGroupId_FK = 195

进行了修改,这里 InnerJoin 是一个与 User 具有 1-1 关系的虚拟表。
InnerJoin 中的列是内连接子查询的返回值

User 和 InnerJoin

DetachedCriteria forUser = DetachedCriteria.For<User>();
forUser.CreateCriteria("InnerJoin");

现在您可以使用拦截器来编辑查询

public interface CustomInterceptor : IInterceptor, EmptyInterceptor
{    
 SqlString IInterceptor.OnPrepareStatement(SqlString sql)
 {
    string query = sql.ToString();
     if (query.Contains("InnerJoin "))
     {
        sql = sql.Replace("InnerJoin ", "(select [vals] form dbo.DailyInfo [where conditions])");
     }
     return sql;
 }
}

对于来自多个表(包括连接子查询)的返回值,您可以使用 NHibernate DTO
会话是这样的

CustomInterceptor custonInterceptor=new CustomInterceptor(); 

sessionFactory.OpenSession(custonInterceptor);

最终查询将是你想要得到的

Same problem I encountered and i didn't get any solutions.So i made a hack with interceptor

Query Generated by Criteria

SELECT u.Id as Id, 
u.Login as Login, 
u.FirstName as FirstName, 
u.LastName as LastName, 
gm.UserGroupId_FK as UserGroupId,
inner.Data1,
inner.Data2,
inner.Data3
FROM dbo.User u inner join 
dbo.GroupMember gm on u.Id = gm.UserAnchorId_FK 
InnerJoin inner ON inner.UserAnchorId_FK = u.Id
WHERE gm.UserGroupId_FK = 195

Here InnerJoin is a dummy table which has 1-1 relation with User.
Columns in InnerJoin are return values of inner join sub query

Criteria for User and InnerJoin

DetachedCriteria forUser = DetachedCriteria.For<User>();
forUser.CreateCriteria("InnerJoin");

Now you can make interceptor to edit the query

public interface CustomInterceptor : IInterceptor, EmptyInterceptor
{    
 SqlString IInterceptor.OnPrepareStatement(SqlString sql)
 {
    string query = sql.ToString();
     if (query.Contains("InnerJoin "))
     {
        sql = sql.Replace("InnerJoin ", "(select [vals] form dbo.DailyInfo [where conditions])");
     }
     return sql;
 }
}

For Return values from multiple tables including joined sub query you can have to use NHibernate DTO
And the session is like this

CustomInterceptor custonInterceptor=new CustomInterceptor(); 

sessionFactory.OpenSession(custonInterceptor);

And the final query will be like what exactly you want to get

执手闯天涯 2024-07-27 03:55:48

就映射关系而言,听起来 User 和 DailyInfo 之间有一对多关系:

<!-- User mapping -->
<bag name="DailyInfos" inverse="true">
    <key column="UserAnchorId_FK" />
    <one-to-many class="Namespace.To.DailyInfo, Namespace" />
</bag>

<!-- DailyInfo mapping -->
<many-to-one name="User" column="UserAnchorId_FK" />

至于其余的,我目前还不完全确定......听起来你可能有很多-通过 GroupMember 表在 UserGroup 之间进行一对多,这可能是一个复杂的因素。 请记住,您可以对条件执行 .CreateCriteria("Association path", jointype) 来创建具有指定连接类型的子条件。 发布类/表关系的概要可能会有所帮助。

As far as mapping the relationship, it sounds like you have a one-to-many relationship between User and DailyInfo:

<!-- User mapping -->
<bag name="DailyInfos" inverse="true">
    <key column="UserAnchorId_FK" />
    <one-to-many class="Namespace.To.DailyInfo, Namespace" />
</bag>

<!-- DailyInfo mapping -->
<many-to-one name="User" column="UserAnchorId_FK" />

As for the rest, I'm not entirely sure at the moment... it sounds like you may have a many-to-many between User and Group via the GroupMember table, which may be a complicating factor. Keep in mind that you can do .CreateCriteria("Association path", jointype) on a criteria to create a sub-criteria with the specified join type. Posting a rundown of your class/table relationships might help.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文