Преобразуйте EntityModel в DTO, используя & ldquo; Basic & rdquo; Пользовательский метод

Единственный способ, без динамического построения запросов, состоит в жестком коде в каждой комбинации и выборе того, который вы хотите.

Если имя таблицы является параметром для хранимой процедуры, это может быть в IF-блоках. Но это неудобно.

Если поля из каждой таблицы одинаковы, вы можете объединить таблицы вместе и выбрать из них ...

CREATE VIEW myUnifiedStructure AS
      SELECT 'Table1' AS tableName, * FROM Table1
UNION SELECT 'Table2' AS tableName, * FROM Table2
UNION SELECT 'Table3' AS tableName, * FROM Table3
-- etc

SELECT * FROM myUnifiedStructure WHERE tableName = 'Table1'

Если поля в каждой таблице различны, вас может интересовать только подмножество полей ...

CREATE VIEW myUnifiedStructure AS
      SELECT 'Table1' AS tableName, field1 AS field1, field4 AS field2 FROM Table1
UNION SELECT 'Table2' AS tableName, field2 AS field1, field3 AS field2 FROM Table2
UNION SELECT 'Table3' AS tableName, field2 AS field1, field4 AS field2 FROM Table3
-- etc

Или вы можете передать NULL для полей, которые не существуют в исходной таблице ...

CREATE VIEW myUnifiedStructure AS
      SELECT 'Table1' AS tableName, NULL   AS field1, field2 AS field2 FROM Table1
UNION SELECT 'Table2' AS tableName, field1 AS field1, field2 AS field2 FROM Table2
UNION SELECT 'Table3' AS tableName, field1 AS field1, NULL   AS field2 FROM Table3
-- etc
0
задан Lee Tickett 18 March 2019 в 12:44
поделиться

2 ответа

Entity Framework не знает, как перевести ваш метод. Вы должны использовать метод, который возвращает Expression<Func<TsrEvent,EventModel>>, или свойство, которое его хранит.

public List<EventModel> GetEvents(bool showInactive, bool showPastEvents)
{
    return eventRepository
        .GetEvents(_customerId, showInactive, showPastEvents)
        .Select(ConvertPocoToModelExpr)
        .ToList();
}

private static Expression<Func<TsrEvent,EventModel>> ConvertPocoToModelExpr =>  (x)=>new EventModel()
    {
        Id = x.EventId,
        Name = x.EventName,
        Capacity = x.EventCapacity,
        Active = x.EventActive                
    };
0
ответ дан Raik 18 March 2019 в 12:44
поделиться

Вы должны знать о различиях между IEnumerable и IQueryable.

Объект IEnumerable содержит все для перечисления в последовательности. Вы можете запросить первый элемент, и как только у вас появится элемент, вы можете запросить следующий, если есть следующий. IEnumerable должен обрабатываться локально вашим процессом.

Перечисление на самом низком уровне выполняется путем запроса перечислителя и повторного вызова MoveNext до тех пор, пока вам больше не понадобятся элементы. Например:

IEnumerable<Student> students = ...
IEnumerator<Student> studentEnumerator = students.GetEnumerator();
while (studentEnumerator.MoveNext())
{
    // there is still a Student to process:
    Student student = studentEnumerator.Current;
    ProcessStudent(student);
}

Вы можете сделать это явно, или неявно вызвать его, используя foreach или одну из функций LINQ.

С другой стороны, IQueryable предназначен для обработки другим процессом, обычно системой управления базами данных. IQueryable содержит Expression и Provider. Expression выражает запрос, который должен быть выполнен в некотором общем формате. Provider знает, кто должен выполнять запрос (обычно это система управления базами данных), и язык, который использует этот процесс (обычно что-то вроде SQL).

Как только вы начинаете перечисление, вызывая GetEnumerator, Expression отправляется Provider, который пытается перевести Expression в SQL и выполняет запрос. Извлеченные данные помещаются в перечислимую последовательность, и перечислитель возвращается.

Вернуться к вашему вопросу

Проблема в том, что SQL не знает ConvertPocoToModel. Следовательно, ваш провайдер не может конвертировать Expression. Компилятор не может обнаружить это, потому что он не знает, насколько умен ваш Provider. Вот почему вы не получите эту ошибку, пока не позвоните GetEnumerator, в вашем случае - ToList.

Решение

Решение - создать функцию, которая изменит выражение. Самый простой способ - это функция расширения. См. Методы расширения демистифицированы . Таким образом, вы можете использовать его как любой другой метод LINQ:

public static IQueryable<EventModel> ToEventModels(this IQueryable<TsrEvent> tsrEvents)
{
    return tsrEvent.Select(tsrEvent =>  new EventModel
    {
        Id = tsrEvent.EventId,
        Name = tsrEvent.EventName,
        Capacity = tsrEvent.EventCapacity,
        Active = tsrEvent.EventActive                
    };
}

Обратите внимание, что я опускаю () в конструкторе: SQL не может вызывать конструкторы!

Использование: [1142 ]

var result = dbContext.TsrEvents
     .Where(tsrEvent => tsrEvent.Active && tsrEvent.Date == Today)
     .ToEventModels()
     .GroupBy(...)
     ... etc

Или, если ваш GetEvents возвращает IQueryable<TsrEvents>

return eventRepository.GetEvents(_customerId, showInactive, showPastEvents)
      .ToEventModels();

Заключительное замечание

Лучше позволить вашим данным- Функции fetch возвращают IQueryable<...> и IEnumerable<...> как можно дольше. Пусть только конечный пользователь материализует запрос. Было бы напрасной тратой вычислительной мощности, если вы выполняете ToList(), а ваш абонент хочет только FirstOrDefault()

0
ответ дан Harald Coppoolse 18 March 2019 в 12:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: