EF Core LINQ Где с расширением методы не переводятся в SQL - PullRequest
0 голосов
/ 13 февраля 2020

С учетом следующего запроса:

context.ToolingOrders
.Include(r => r.ToolingOrderDetails)
.Include(r => r.PurchaseOrder)
.Where(r => r.VendorId.EqualsOrNull(filter.VendorId) && 
            r.PoNumber.ContainsOrEmpty(filter.PoNumber))

Я использую эти методы расширения для сохранения некоторого кода:

 public static class FilterExtensions
 {
        public static bool ContainsOrEmpty(this string source, string toCheck)
        {
            return string.IsNullOrWhiteSpace(toCheck) || source?.IndexOf(toCheck, StringComparison.OrdinalIgnoreCase) >= 0;
        }

        public static bool EqualsOrNull(this int source, int? toCheck)
        {
            return !toCheck.HasValue || source == toCheck;
        }
 }

Проблема заключается в том, что из-за этих методов расширения часть Where является не переведено на SQL.

Я использую. Net Core 2.2, у которого есть функция оценки на стороне клиента , которая полностью скрывает эту проблему, но профилировщик SQL показывает это в любом случае.

Есть ли способ заставить это работать, или я должен написать каждую часть части where в явном виде?

1 Ответ

0 голосов
/ 13 февраля 2020

Вы можете расширить IQueryable для вашего указанного c объекта.
Возьмите, к примеру, следующий объект:

public class MyObject
{
    public string MyProperty;
}

Вы можете написать расширение следующим образом:

public static class MyQueryExtension
{
    public static IQueryable<MyObject> WhereMyPropertyNull(this IQueryable<MyObject> queryable)
    {
        return queryable.Where(obj => obj.MyProperty == null);
    }
}

И используйте это следующим образом:

var queryable = new List<MyObject>().AsQueryable();
var result = queryable.WhereMyPropertyNull().ToList();

РЕДАКТИРОВАТЬ

На основе некоторых отзывов я обновил свой ответ для обработки обобщений.

public static class Extensions
    {
        public static IQueryable<TEntity> EqualOrNull<TEntity, TProperty>(this IQueryable<TEntity> source, Func<TEntity, TProperty> selector, TProperty match)
        {
            return source.Where(entity => Match(selector.Invoke(entity), match));
        }

        private static bool Match<TEntity, TProperty>(TEntity entity, TProperty match)
        {
            if (entity == null) {
                return true;
            } else {
                return entity.Equals(match);
            }
        }
    }

Может использоваться для передачи значения свойства в оператор where:

            var list = new List<MyObject>();
            list.Add(new MyObject {MyProperty = "Test"});
            list.Add(new MyObject {MyProperty = "NoMatch"});
            list.Add(new MyObject {MyProperty = null});

            var result = list.AsQueryable()
                .EqualOrNull(o => o.MyProperty, "Test")
                .ToList();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...