简体   繁体   English

LINQ 到 NHibernate 加入 - 查询每组的最新 N - NotSupportedException

[英]LINQ to NHibernate join - Query latest N per group - NotSupportedException

I'm trying to get the last message sent to each customer.我正在尝试将最后一条消息发送给每个客户。 But I'm getting a NotSupportedException without any additional details.但我得到一个 NotSupportedException 没有任何额外的细节。 I'm unfamiliar with the join method of LINQ to NHibernate since this is the first time using it.我不熟悉 LINQ 到 NHibernate 的连接方法,因为这是第一次使用它。 Can someone please explain what is wrong with my query and why I'm getting this error?有人可以解释我的查询有什么问题以及为什么会出现此错误吗? Here is my query and the error:这是我的查询和错误:

var messages = _session.Query<Communication>();     

return messages.Join(
                _session.Query<Communication>().GroupBy(m => m.Customer),
                x => new { x.Customer, x.Message.CreatedOn },
                g => new { Customer= g.Key, CreatedOn = g.Max(p => p.Message.CreatedOn) },
                (x, g) => x)
                .ToList();

System.NotSupportedException: query ( query ( select_from ( from ( range App.Core.Customer m ) ) ( select m ) ) ) System.NotSupportedException:查询(查询(select_from(从(范围 App.Core.Customer m))(select m)))

Entities:实体:

public class Communication
{
    public Message Message { get; set; }
    public Customer Customer { get; set; }
    ...
}

public class Message
{
    public DateTime CreatedOn { get; set; }
    public string Subject { get; set; }
    public string Body { get; set; }
    ...
}

Can someone please explain what is wrong with my query and why I'm getting this error?有人可以解释我的查询有什么问题以及为什么会出现此错误吗?

NHibernate doesn't support joins on sub-query. NHibernate 不支持子查询连接。 That gives you NotSupportedException .这给了你NotSupportedException

It also has some issues with group by sub-queries (see for details How to query the first entry in each group in NHibernate ).它也有一些分组子查询的问题(有关详细信息,请参阅如何查询 NHibernate 中每个组中的第一个条目)。 But using last technique described in this answer you can rewrite your query to something like:但是使用此答案中描述的最后一种技术,您可以将查询重写为:

var results = session.Query<Communication>()
        .Where(c => c == session.Query<Communication>()
                            .Where(cs => cs.Customer == c.Customer)
                            .OrderByDescending(cs => cs.Message.CreatedOn)
                            .First()
        ).ToList();

I'm assuming a Communication is like a thread of multiple messages, and CustomerId exists at the Communication level, and then messages have a CommunicationId and a CreatedOn.我假设一个通信就像一个多条消息的线程,并且 CustomerId 存在于通信级别,然后消息有一个 CommunicationId 和一个 CreatedOn。 I don't claim to be able to provide the nHibernate/LINQ syntax but you could perhaps do it with raw SQL:我不声称能够提供 nHibernate/LINQ 语法,但您也许可以使用原始 SQL 来做到这一点:

var m = _session.CreateSQLQuery(@"

  SELECT m.Id, m.CommunicationId, m.CreatedOn, m.<put a list of all other columns in messages here>
  FROM
    (SELECT *, ROW_NUMBER() OVER(PARTITION BY CommunicationId ORDER BY CreatedOn DESC) rown FROM Messages) m 
  WHERE m.rown = 1")
.AddEntity(typeof(Message))
.List<Message>();

You'll need to fill in the <... > with all the other columns in Message.您需要使用 Message 中的所有其他列填写<... > I think (I've only looked at posts on the web about how to run raw SQL in nH) that this will select all the latest Messages per Communication.. And maybe then crawling round the object tree would be like m.First().Communication.Customer.Name etc I think (I've only looked at posts on the web about how to run raw SQL in nH) that this will select all the latest Messages per Communication.. And maybe then crawling round the object tree would be like m.First().Communication.Customer.Name

ie Hopefully from these you can join/navigate onto the Communications, get the Customer etc. I don't know enough about raw querying nH to know how to get it to form an object graph that includes the Communication in one hit, but you could use this query:即希望从这些您可以加入/导航到通信,获取客户等。我对原始查询 nH 知之甚少,不知道如何让它形成一个 object 图表,其中包括一次点击中的通信,但你可以使用这个查询:

  SELECT d.*
  FROM
    (SELECT *, ROW_NUMBER() OVER(PARTITION BY c.CustomerId ORDER BY CreatedOn DESC) rown FROM Messages m INNER JOIN Communication c ON m.CommunicationId = c.Id) d 
  WHERE d.rown = 1

To get all the latest messages per customer (subtly different than latest message per comm, if one customer has two comms concurrent), and combine it with the advice here to make the results a dynamic获取每个客户的所有最新消息(如果一个客户同时有两个通信,则与每个通信的最新消息略有不同),并将其与此处的建议相结合以使结果动态

Maybe this is what you want to do?也许这就是你想要做的?

return _session
          .Query<Communication>()
          .GroupBy(e => e.Customer)
          .Select(g => new {Customer = g.Key, MaxDate = g.Max(r => r.Message.CreatedOn)})
          .ToList()

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

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