C # Dynamic Linq: реализовать «как» в предложении Where - PullRequest
10 голосов
/ 08 апреля 2019

Итак, я хочу сделать общий сортировщик для моих данных. У меня есть этот код для получения данных из базы данных, которая будет извлекать только те данные, которые содержат value.

using System.Linq.Dynamic;

public static IQueryable<object> SortList(string searchString, Type modelType, 
    IQueryable<object> model)
{
    ....

    string toStringPredicate = type == typeof(string) ? propertyName + 
        ".Contains(@0)" : propertyName + ".ToString().Contains(@0)";
    model = model.Where(propertyName + " != NULL AND " + toStringPredicate, value);
}

Модель такая:

public class ManageSubscriberItems
{
    public int? UserId { get; set; }
    public string Email { get; set; }
    public Guid SubscriberId { get; set; }
}

Когда я звоню:

models = (IQueryable<ManageSubscriberItems>)EcommerceCMS.Helpers.FilterHelper
    .SortList(searchString, typeof(ManageSubscriberItems), models);

if(models.Any())

Выдает эту ошибку:

"LINQ to Entities не распознает метод 'System.String Метод ToString (), и этот метод не может быть переведен в хранилище выражение ".


EDIT

Я нашел проблему, но все еще не могу ее исправить. Поэтому, если свойство не string, оно вызовет ошибку при вызове .ToString().Contains().

model = model.Where(propertyName + " != NULL AND " + propertyName + 
    ".ToString().Contains(@0)", value);

Я хочу реализовать LIKE в запросе. Кто-нибудь может мне помочь?

Ответы [ 4 ]

6 голосов
/ 12 апреля 2019

Если вы используете System.Linq.Dynamic.Core с EF Core , у вас есть возможность использовать

var q = context.Cars.Where(config, "DynamicFunctions.Like(Brand, \"%a%\")");

См. Эту ссылку для примера: https://github.com/StefH/System.Linq.Dynamic.Core/blob/6fc7fcc43b248940560a0728c4d181e191f9eec1/src-console/ConsoleAppEF2.1.1/Program.cs#L117

И я только что проверил в linqpad подключение к реальной базе данных, и такой код просто работает?

var result1 = Entity1s.Where("Url != NULL AND it.Url.Contains(@0)", "e");


[ОБНОВЛЕНИЕ 2019-04-17]]

Если вы не знаете тип, вы можете привести его к object , а затем привести к string .

Код:

var r = Entity1s.Select("string(object(Rating))").Where("Contains(@0)", "6");
4 голосов
/ 15 апреля 2019

, поэтому проблема в том, что IQueryable происходит на SQL сервере, а не в C # ... поэтому SQL сервер ничего не знает о .toString () метод. so => ​​и Как оператор он сам работает со строками .. так что это типы данных nvarchar и varchar в SQL-сервере. Я мог бы привести пример того, как этого добиться, если бы вы могли рассказать мне больше о своей проблеме и о том, чего вы хотите достичь. мог бы сделать образец.

0 голосов
/ 19 апреля 2019

Итак, я хочу сделать общий сортировщик для моих данных.

вместо исправления 'invoke проблема' , общий способ должен использовать дженерики, такие как

public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, 
                                       string property,
                                       bool asc = true) where T : class
{
    //STEP 1: Validate MORE!
    var searchProperty = typeof(T).GetProperty(property);
    if (searchProperty == null) throw new ArgumentException("property");

     ....

    //STEP 2: Create the OrderBy property selector
    var parameter = Expression.Parameter(typeof(T), "o");
    var selectorExpr = Expression.Lambda(Expression.Property(parameter, property), parameter)        

    //STEP 3: Update the IQueryable expression to include OrderBy
    Expression queryExpr = source.Expression;
    queryExpr = Expression.Call(typeof(Queryable), asc ? "OrderBy" : "OrderByDescending",
                                  new Type[] { source.ElementType, searchProperty.PropertyType },
                                 queryExpr, 
                                selectorExpr);

    return source.Provider.CreateQuery<T>(queryExpr);
}

с именем и строкой свойства, обычно используемыми для «сортировки столбцов» данных.

Далее идут предикаты отношений, и «Linq.Dynamic» кажется разумным при работе с нуля, но существует общая и каноническая форма , существующая .

0 голосов
/ 16 апреля 2019

У вас уже есть «Like» в Linq, который может работать в базе данных и работать со строками, он называется «IndexOf»:

 ((IQueryable)model).Where(m => m.Property.IndexOf(searchString) == 1);

По данным MSDN: IndexOf (строка)

' Начинающаяся с нуля позиция индекса, если эта строка найдена, или -1, если это не так. Если значение пусто, возвращаемое значение равно 0. '

...