#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();