1

I need to execute a query that joins two tables, groups by a value, and returns the group key and a count.

CREATE TABLE Message(
  ID INT NOT NULL
, Note NVARCHAR(128));

CREATE TABLE Message_Users(
  MessageID INT NOT NULL
, UserID NVARCHAR(128) NOT NULL);

I need to execute this query:

SELECT mu.UserID, COUNT(m.ID)
FROM Message m
JOIN Message_Users mu
   ON m.ID = mu.MessageID
GROUP BY mu.UserID;

How can I do this using NHibernate? The Message table is mapped as follows:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="DataModel" namespace="DataModel.Message">
  <class name="Message" table="Message">
    <id name="ID">
      <generator class="native" />
    </id>
    <bag name="AssociatedUsers" table="Message_Users" lazy="false">
      <key column="MessageID" />
      <element column="UserID" type="System.String" />
    </bag>
  </class>
</hibernate-mapping>

I have looked at several other questions, but none meet quite this use case (plenty of GroupBy, but not with an association; plenty of join, but not with a group by)

Two directions I have started going in:

// First attempt

// Doesn't work as message.AssociatedUsers is a collection, so mu.Key is actually a collection
var query = transactionContext.Session.Query<Message>();    
var r = from message in query
        group message by message.AssociatedUsers into mu
        select new {UserID = mu.Key, Count = mu.Count()};

// Second attempt

var query = transactionContext.Session.QueryOver<Message>();
var join = query.Right.JoinQueryOver<string>(_message => _message.AssociatedUsers);
var select = join.Select(
      // Select generic parameter doesn't seem to be related to the type of the join (<Message, string>)
    Projections.Group<string>(... 
Community
  • 1
  • 1
Travis
  • 2,654
  • 4
  • 26
  • 46

1 Answers1

2

not tested

// Option 1
var r = from message in Session.Query<Message>()
        from userid in message.AssociatedUsers
        group userid by userid into g
        select new { UserID = g.Key, Count = g.Count() };

// Option 2
string userId = null;
var r = Session.QueryOver<Message>()
    .JoinQueryOver<string>(m => m.AssociatedUsers, () => userId)
    .SelectList(list => list
        .SelectGroup(() => userid)
        .Select(Projections.Count()))
    .List<object[]>();
Firo
  • 30,626
  • 4
  • 55
  • 94
  • Pure gold, option 1 worked like a charm. I didn't think to do an implicit join on the association itself - makes sense now that I see it. Thanks =) – Travis Aug 29 '12 at 02:20