LINQ выберите из Queryable присоединения к списку

c# entity-framework linq

85 просмотра

2 ответа

Я использую EF, чтобы присоединиться к таблице, используя список.

У меня есть таблица посещаемости:

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

Кроме того, у меня есть посещаемость IEnumerable в памяти той же структуры, назовем ее newAttendance.

Мне нужно найти все записи из таблицы посещаемости, которая соответствует UserBaseId и ClassroomId в списке newAttendance.

пока я пробовал это,

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
))

Также попытался присоединиться, но это не сработало.

ТИА

Автор: SJMan Источник Размещён: 08.11.2019 11:02

Ответы (2)


0 плюса

Я считаю, что это должно делать то, что вы хотите:

var entriesInAttendanceTable = context.Attendance.Where(x => (newAttendance.Any(
    y => y.UserBaseId == x.UserBaseId && y.ClassRoomId == x.ClassRoomId)));
Автор: smead Размещён: 20.08.2016 08:18

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список большой.

Автор: Ivan Stoev Размещён: 20.08.2016 11:57
Вопросы из категории :
32x32