简体   繁体   中英

Translate SQL query into a LINQ expression

So I'm developing an easy inbox chat. I need to gather all latest user's direct messages. For this I wrote an SQL query which works as expected, but the LINQ version doesn't . Anybody have ideas of how do this SQL should be properly translated into LINQ?

This

CreatedAt Content ReceiverId CreatedById
1/1/2021  Hello!  2          1
1/1/2021  Hello!  3          1
1/2/2021  Hi!     1          2

Should result into this

 CreatedAt Content ReceiverId CreatedById
 1/1/2021  Hello!  3          1
 1/2/2021  Hi!     1          2

This is an SQL query ran on MSSQL:

select created_at = MAX(created_at) from messages
where
  receiver_id = '2921295d-f0c0-4162-ec8f-08d9d5c5b3f5' or 
  created_by_id = '2921295d-f0c0-4162-ec8f-08d9d5c5b3f5'
group by IIF(created_by_id = receiver_id, created_by_id, receiver_id)
order by created_at

LINQ:

(from message in Query.Where(x => x.ReceiverId == 1 || x.CreatedById == 1)
    group message by new { message.CreatedById, message.ReceiverId }
    into groupped
    select new InboxItemDto
    {
        CreatedAt = groupped.Max(z => z.CreatedAt),
        Content = groupped.FirstOrDefault().Content,
        Receiver = groupped.Key.CreatedById == 1
           ? groupped.FirstOrDefault().Receiver.FirstName
           : groupped.FirstOrDefault().CreatedBy.FirstName,
        Type = groupped.FirstOrDefault().Type

    }).OrderByDescending(x => x.CreatedAt)
    .ToList();

Id's should be integers not strings. You have '1' which is a string. How can receiver_id and created_by id be both 1 and create_by be greater than receiver_id? Try following:

    class Program
    {

        static void Main(string[] args)
        {
            List<Message> messages = new List<Message>();

            var created_at = messages.Where(x => ((x.receiver_id == 1) || (x.created_by_id == 1)) && (x.created_by_id > x.receiver_id))
                .OrderBy(x => x.created_at)
                .ThenBy(x => x.desc)
                .GroupBy(x => new object[] { x.created_by_id, x.receiver_id })
                .ToList();            
        }
    }
    public class Message
    {
        public int receiver_id { get; set; }
        public int created_by_id { get; set; }
        public DateTime created_at {get;set;}
        public string desc { get; set; }
    }

Try the following query. It should return desired result.

Small note: I do not see reason of this condition IIF(created_by_id = receiver_id, created_by_id, receiver_id) , it is always receiver_id . Anyway added to the query.

var filteredWithKey =  
    from message in Query
    where message.ReceiverId == 1 || message.CreatedById == 1
    select new 
    {
        UserKey = message.ReceiverId == message.CreatedById ? message.CreatedById : message.ReceiverId,
        Message = message
    };

var query =
    from k in filteredWithKey.Select(k => new { k.UserKey }).Distinct()
    from lastMessage in filteredWithKey
        .Where(x => x.UserKey == k.UserKey)
        .Select(x => x.Message)
        .OrderByDescending(m => m.CreatedAt)
        .Take(1)
    select lastMessage;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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