如何根据ID组合查询linq

How to query linq based on combinations of IDs

UserNotificationTypeDeliveryChoice - 已采用的组合

已采用的组合 (1,2),(3,2),(4,1),(4,2)

NotificationGroupUserType - 可能的组合

基于此table,自由组合为: (1,1),(5,2)

任务: 我需要来自 NotificationGroupUserType table 的组合,其中不包含已采用的组合

一个例子:

List<int> notificationGroupIds = selectedNotificationsByUser
    .Select(m => (int)m.NotificationGroupId)
    .ToList();
List<int> deliveryTypeIds = selectedNotificationsByUser
    .Select(m => (int)m.DeliveryTypeId)
    .ToList();

var result = _dbContext.NotificationGroupUserType
    .Include(m => m.NotificationGroup)
    .Include(m => m.DeliveryType)
    .Where(m => m.UserTypeId == (int)userType
        && !notificationGroupIds.Contains((int)m.NotificationGroupId)
        || !deliveryTypeIds.Contains((int)m.DeliveryTypeId)
    )
    .Select(m => new NotificationGroupUserType()
    {
        DeliveryType = m.DeliveryType,
        NotificationGroup = m.NotificationGroup
    })
    .ToList();

它 returns 只是 (5,2),因为它排除了 (1,1),因为 NotificationGroupId 已经存在,但不是与 1 的组合!

这是因为您独立测试了两个 ID,而不是成对测试。尝试使用匿名类型:

var notifications = selectedNotificationsByUser
    .Select(n => new { n.NotificationGroupId, n.DeliveryTypeId })
    .Distinct()
    .ToList();

var result = _dbContext.NotificationGroupUserType
    .Include(m => m.NotificationGroup)
    .Include(m => m.DeliveryType)
    .Where(m => m.UserTypeId == (int)userType &&
        !notifications.Contains(new { m.NotificationGroupId, m.DeliveryTypeId }))
    .Select(m => new NotificationGroupUserType() {
        DeliveryType = m.DeliveryType,
        NotificationGroup = m.NotificationGroup
    })
    .ToList();

如果 LINQ-to-SQL 无法将表达式转换为 SQL,您可以试试这个:

var result = _dbContext.NotificationGroupUserType
    .Include(m => m.NotificationGroup)
    .Include(m => m.DeliveryType)
    .Where(m => m.UserTypeId == (int)userType)
    .AsEnumerable() // Following part is LINQ-to-Objects
    .Where(m => !notifications.Contains(new { m.NotificationGroupId, m.DeliveryTypeId }))
    .Select(m => new NotificationGroupUserType() {
        DeliveryType = m.DeliveryType,
        NotificationGroup = m.NotificationGroup
    })
    .ToList();

尝试以下操作:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace ConsoleApplication1
{
    class Program
    {
         static void Main(string[] args)
         {
             DataTable dt = new DataTable();
             dt.Columns.Add("NotificationGroupId", typeof(int));
             dt.Columns.Add("DeliveryTypeId", typeof(int));

             dt.Rows.Add(new object[] { 1, 1 });
             dt.Rows.Add(new object[] { 3, 2 });
             dt.Rows.Add(new object[] { 4, 1 });
             dt.Rows.Add(new object[] { 4, 2 });
             dt.Rows.Add(new object[] { 5, 2 });
             dt.Rows.Add(new object[] { 1, 1 });
             dt.Rows.Add(new object[] { 3, 2 });
             dt.Rows.Add(new object[] { 4, 1 });
             dt.Rows.Add(new object[] { 4, 2 });
             dt.Rows.Add(new object[] { 5, 2 });

             List <CompareID> ids = dt.AsEnumerable()
                 .Select(x => new CompareID() { NotificationGroupId = x.Field<int>("NotificationGroupId"), DeliveryTypeId = x.Field<int>("DeliveryTypeId") })
                 .Distinct()
                 .ToList();

             Boolean found = ids.Contains(new CompareID() { NotificationGroupId = 5, DeliveryTypeId = 5 });

         }
    }
    public class CompareID : IEquatable <CompareID>
    {
        public int NotificationGroupId { get; set; }
        public int DeliveryTypeId { get; set; }

        public bool Equals(CompareID other)
        {
            if ((this.NotificationGroupId == other.NotificationGroupId) && (this.DeliveryTypeId == other.DeliveryTypeId))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public override bool Equals(Object obj)
        {
            return this.Equals((CompareID)obj);
        }

        public override int GetHashCode()
        {
            return (NotificationGroupId.ToString() + "^" + DeliveryTypeId.ToString()).GetHashCode();
        }
    }

}