Создание выражения для использования с Entity Framework 6 - PullRequest
2 голосов
/ 18 июня 2020

У меня есть следующий метод, который запускает IQueryable.

public static IQueryable<StorageDetail> QueryStorageDetails(ApplicationDbContext dbContext, DateRange dateRange)
{
    return from detail in dbContext.StorageDetails
           where (detail.ArrivalDate != null && detail.ArrivalDate <= dateRange.EndDate &&
                (detail.ReleaseDate == null || detail.ReleaseDate >= dateRange.StartDate)) ||
                (detail.TakeOrPayStartDate != null && detail.TakeOrPayStartDate <= dateRange.EndDate &&
                (detail.TakeOrPayEndDate == null || detail.TakeOrPayEndDate >= dateRange.StartDate))
           select detail;
}

Я попытался реорганизовать его следующим образом.

public static bool FilterByDate(StorageDetail detail, DateRange dateRange)
{
    return (detail.ArrivalDate != null && detail.ArrivalDate <= dateRange.EndDate &&
        (detail.ReleaseDate == null || detail.ReleaseDate >= dateRange.StartDate)) ||
        (detail.TakeOrPayStartDate != null && detail.TakeOrPayStartDate <= dateRange.EndDate &&
        (detail.TakeOrPayEndDate == null || detail.TakeOrPayEndDate >= dateRange.StartDate));
}

public static IQueryable<StorageDetail> QueryStorageDetails(ApplicationDbContext dbContext, DateRange dateRange)
{
    return dbContext.StorageDetails
        .Where(d => FilterByDate(d, dateRange));
}

Но это вызывает ошибку.

The LINQ expression 'DbSet<StorageDetail>
    .Where(s => QueryHelper.FilterByDate(
        detail: s, 
        dateRange: __dateRange_0))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

Я почти уверен, что есть способ сделать это, возможно, создав Expression, но я не могу понять синтаксис правильно. Кто-нибудь знает, как это сделать?

1 Ответ

2 голосов
/ 18 июня 2020

FilterByDate должен вернуть Expression<Func<StorageDetail, bool>>, чтобы EF смогла преобразовать ваш код в запрос. Попробуйте примерно так:

public static Expression<Func<StorageDetail, bool>> FilterByDate(DateRange dateRange)
{
    return detail => (detail.ArrivalDate != null && detail.ArrivalDate <= dateRange.EndDate &&
        (detail.ReleaseDate == null || detail.ReleaseDate >= dateRange.StartDate)) ||
        (detail.TakeOrPayStartDate != null && detail.TakeOrPayStartDate <= dateRange.EndDate &&
        (detail.TakeOrPayEndDate == null || detail.TakeOrPayEndDate >= dateRange.StartDate));
}

и

public static IQueryable<StorageDetail> QueryStorageDetails(ApplicationDbContext dbContext, DateRange dateRange)
{
    return dbContext.StorageDetails
        .Where(FilterByDate(dateRange));
}
...