Linq to Entities Комплексный динамический поиск - PullRequest
0 голосов
/ 13 октября 2011

Мы используем Entity Framework (коннектор MySQL) и создаем центральное средство поиска в нашем веб-приложении.

Эта ссылка - почти то, что мне нужно, за исключением того факта, что он использует предопределенные объекты и свойства. В нашем сценарии поиска у нас будет динамическое количество поисковых терминов и полей (т. Е. Пользователь выбирает для поиска по фамилии, значению и городу или поставщика и консультанта).

Можно ли достичь такого рода функциональности с помощью LINQ, чтобы мы могли использовать механизм отложенной загрузки? Я действительно хотел избежать генерации строк SQL, если это возможно. Я посмотрел на Dynamic LINQ с деревьями выражений , но не смог заставить его работать (или this ).

Ответы [ 2 ]

0 голосов
/ 03 декабря 2011

с прошлой недели мы столкнулись с подобной проблемой, вот идея, которую я только что предложил для нее. Я поделился этим с тобой.

interface IPerson
{            
    DateTime BirthDay { get; set; }

    string City { get; set; }            

    string FirstName { get; set; }

    string LastName { get; set; }
}

interface IFilter { }

interface IPersonFilter : IFilter { }

class PersonFilter : IPersonFilter
{            
    public DateTime? BirthDay { get; set; }

    public string City { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }            
}

static IQueryable<TSource> ApplyFilter<TSource, TFilter>(IQueryable<TSource> source, TFilter filter) where TFilter : IFilter
{
    const BindingFlags bindingFlags = BindingFlags.Public|BindingFlags.Instance|BindingFlags.GetProperty;

    var retval = source;
    foreach (var filterProperty in filter.GetType().GetProperties(bindingFlags))
    {
        var elementParameter = Expression.Parameter(source.ElementType, "type");
        var elementProperty  = Expression.Property(elementParameter, filterProperty.Name);

        var value = filterProperty.GetGetMethod().Invoke(filter, null);
        if (value != null)
        {
            var constantValue = Expression.Constant(value, elementProperty.Type);
            var expression = Expression.Equal(elementProperty, constantValue);
            retval = retval.Where(Expression.Lambda<Func<TSource, bool>>(expression, elementParameter));
        }
    }

    return retval;
}

так что идея в том, что у вас есть фильтр, в котором имена свойств фильтра совпадают с именами свойств объекта, для которого вы хотите запустить фильтр. и если значение свойства не равно нулю, я создаю для него выражение. Для простоты я создаю только Expression.Equal выражения, но я думаю о его расширении.

0 голосов
/ 13 октября 2011

Я знаю, что вы указали, что хотите избежать генерации строк SQL, но это часто самый простой способ. (Гораздо проще, чем пользовательские деревья выражений). Если вы делаете это в EF, я рекомендую вам проверить Entity Sql, который работает против вашей концептуальной модели, но допускает больше вариантов динамических запросов, чем LINQ. LINQ действительно подходит для компиляции запросов времени, а не запросов времени выполнения. Вы можете прочитать о Entity SQL на http://msdn.microsoft.com/en-us/library/bb387145.aspx.

...