LINQ从Queryable加入List中选择

时间:2016-08-20 07:50:56

标签: c# entity-framework linq

我正在使用EF使用列表加入表。

我有出勤表:

Attendance
----------
UserBaseId
ClassroomID
Attendance Status ...etc

另外, 我在内存中出现了IEnumerable,结构相同,我们称之为newAttendance。

我需要从出勤表​​中找到与newAttendance列表中的UserBaseId和ClassroomId匹配的所有记录。

到目前为止,我已尝试过这个,

var entriesInAttendanceTable = context.Attendance.Where(
            x => (newAttendance .Select(i => i.UserBaseId).Contains(x.UserBaseId))
            && newAttendance .Select(i => i.ClassRoomId).Contains(x.ClassRoomId)
            ).ToList();

这导致以下SQL查询:

SELECT 
[Extent1].[Id] AS [Id], 

[Extent1].[ClassRoomId] AS [ClassRoomId], 

[Extent1].[UserBaseId] AS [UserBaseId], 
[Extent1].[CreatedOn] AS [CreatedOn], 
[Extent1].[UpdatedOn] AS [UpdatedOn], 
[Extent1].[UpdatedByUser_Id] AS [UpdatedByUser_Id], 
[Extent1].[CreatedByUser_Id] AS [CreatedByUser_Id]
FROM [dbo].[Attendance] AS [Extent1]
WHERE ( EXISTS (SELECT 
    1 AS [C1]
    FROM  ( SELECT 1 AS X ) AS [SingleRowTable1]
    WHERE 1 = 0
)) AND ( EXISTS (SELECT 
    1 AS [C1]
    FROM  ( SELECT 1 AS X ) AS [SingleRowTable2]
    WHERE 1 = 0
))

也试过加入,但它没有用。

TIA

2 个答案:

答案 0 :(得分:0)

我相信这应该做你想做的事情:

var entriesInAttendanceTable = context.Attendance.Where(x => (newAttendance.Any(
    y => y.UserBaseId == x.UserBaseId && y.ClassRoomId == x.ClassRoomId)));

答案 1 :(得分:0)

一般情况下,这不受支持,因此您需要

(A)构建并执行UNION这样的查询:

var entriesInAttendanceTable = newAttendance
    .Select(y => context.Attendance.Where(x => y.FirstName == x.FirstName && y.LastName == x.LastName))
    .Aggregate(Queryable.Union)
    .ToList();

(B)构建并执行基于OR的查询,如下所示:

助手:

public static class QueryableExtensions
{
    public static IQueryable<T> Match<T>(this IQueryable<T> source, IEnumerable<T> target, Expression<Func<T, T, bool>> by)
    {
        var parameter = by.Parameters[0];
        var condition = target
            .Select(item => by.Body.ReplaceParameter(by.Parameters[1], Expression.Constant(item)))
            .DefaultIfEmpty()
            .Aggregate(Expression.OrElse) ?? Expression.Constant(false);
        var predicate = Expression.Lambda<Func<T, bool>>(condition, parameter);
        return source.Where(predicate);
    }

    public static Expression ReplaceParameter(this Expression expression, ParameterExpression source, Expression target)
    {
        return new ParameterReplacer { Source = source, Target = target }.Visit(expression);
    }

    class ParameterReplacer : ExpressionVisitor
    {
        public ParameterExpression Source;
        public Expression Target;
        protected override Expression VisitParameter(ParameterExpression node)
        {
            return node == Source ? Target : base.VisitParameter(node);
        }
    }
}

用法:

var entriesInAttendanceTable = context.Attendance
    .Match(newAttendance, (x, y) => y.FirstName == x.FirstName && y.LastName == x.LastName)
    .ToList();

请注意,如果newAttendance列表很大,则两种解决方案都可能会出现问题。