Как использовать проекцию в LINQ для преобразования сущности в класс DTO

#c# #.net #linq #entity-framework-projection

#c# #.net #linq #entity-framework-projection

Вопрос:

У меня есть скрипт Linq, и я хочу использовать класс проекции для получения данных в тип DTO. Я получил пример для лямбда-эксперимента, но получаю ошибку в скрипте LINQ.

Сценарий Linq:

 public class EziTransactionDto
{
   ... other properties

 public static Expression<Func<EziTransactionEntity, EziTransactionDto>> Projection()
    {
        return eziTransactionDto => new EziTransactionDto
        {
            EziTransactionId = eziTransactionDto.Id,
            LoginSiteID = eziTransactionDto.LoginSiteID,
            WorkCodes = eziTransactionDto.WorkCodes
        };

    }
 

Запрос Linq:

   var ts = (from transaction in _eziTransactionRepository.GetAll<EziTransactionEntity>()
                  where transaction.LoginErrorCode != 0
                  select transaction
                 ).Select(EziTransactionDto.Projection);
 

Ошибка:

введите описание изображения здесь

Комментарии:

1. Проекция — это метод … используйте его как метод, а не как поле

2. почему отрицательный, если не могу ответить на него .. недопустимый вопрос..

3. Select(EziTransactionDto.Projection) => Select(EziTransactionDto.Projection())

Ответ №1:

Я думаю, ключевое Expression слово там нечетное.

Попробуйте это:

 // public static Expression<Func<EziTransactionEntity, EziTransactionDto>> Projection()
public static Func<EziTransactionEntity, EziTransactionDto> Projection()
{
    return eziTransactionDto => new EziTransactionDto
    {
        EziTransactionId = eziTransactionDto.Id,
        LoginSiteID = eziTransactionDto.LoginSiteID,
        WorkCodes = eziTransactionDto.WorkCodes
    };
}
 

Ответ №2:

После первого выбора ваш IQueryable уже извлек данные в локальный процесс и сделал его IEnumerable .

Вы могли бы выполнить это преобразование в своем операторе Select:

 var eziTransactionDtos = _eziTransactionRepository.EziTransactionEntities
    .Where(eziTransactionEntity => eziTransationEntity.LoginErrorCode != 0)
    .Select(eziTransactionEntity => new EziTransactionDto
    {
        EziTransactionId = eziTransactionDto.Id,
        LoginSiteID = eziTransactionDto.LoginSiteID,
        WorkCodes = eziTransactionDto.WorkCodes,
    });
 

Однако, если вам нужно преобразовать EziTransactionEntities в ezitransactiondto в нескольких местах, хорошей идеей будет создать повторно используемый метод расширения для IQueryable<EziTransactionEntities> .

Если вы не знакомы с методами расширения, см. раздел Методы расширения, разоблаченные

 public static IQueryable<EziTransactionDto> ToEziTransactionDto(
    this IQueryable<EziTransactionEntity> eziTransactionEntities)
{
    return eziTransactionEntities.Select(eziTransactionEntity => new EziTransactionDto
    {
        EziTransactionId = eziTransactionDto.Id,
        LoginSiteID = eziTransactionDto.LoginSiteID,
        WorkCodes = eziTransactionDto.WorkCodes,
    });
 

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

 var eziTransactionDtos = eziTransactionRepository.EziTransactionEntities
    .Where(eziTransactionEntity => eziTransationEntity.LoginErrorCode != 0)
    .ToEziTransactionDtos();
 

Повторно используемый:

 var transactionWithoutWorkCodes = eziTransactionRepository.EziTransactionEntities
    .Where(eziTransactionEntity => eziTransationEntity.WorkCode == null)
    .ToEziTransactionDtos();
 

Простота модульного тестирования:

 List<EziTransactionEntity> testItems = ...
List<EziTransactionDto> expectedResults = ...

var testResults = testItems.AsQueryable().ToEziTransactionDtos();
Assert.AreQual(expectedResults, testResults, unorderedTransactionsComparer);
 

Простота в обслуживании: если вы добавите / удалите / измените одно свойство этого преобразования, вам нужно будет сделать это только в одном месте

Ответ №3:

ответ нравится

 public static Expression<Func<EziTransactionEntity, EziTransactionDto>> Projection
    {
        get
        {
            return eziTransactionDto => new EziTransactionDto
            {
                EziTransactionId = eziTransactionDto.Id,
                LoginSiteID = eziTransactionDto.LoginSiteID,
                WorkCodes = eziTransactionDto.WorkCodes
            };
        }
    }
 

..

  var ts = (from transaction in _eziTransactionRepository.GetAll<EziTransactionEntity>()
                  select transaction
                 ).Select(EziTransactionDto.Projection).ToList();