C#动态LINQ:在Where子句中实现"Like"

13

所以我想为我的数据制作一个通用的排序器。我有这段代码从数据库中获取数据,它将仅提取包含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()' 方法,这种方法无法转换成存储表达式。"


编辑

我找到了问题所在,但是仍然无法解决。如果属性不是 string,那么调用 .ToString().Contains() 会抛出错误。

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

我想在查询中实现LIKE操作。有人可以帮忙吗?


请查看 https://learn.microsoft.com/en-us/dotnet/api/system.data.objects.sqlclient.sqlfunctions.stringconvert?redirectedfrom=MSDN&view=netframework-4.7.2#overloads ,我认为您不能在LinQ或EF中使用ToString()。您可以做的是创建一个属性/变量并在查询之前设置其值.ToString(),然后使用该属性/变量(并删除.ToString())。大致如下:https://www.c-sharpcorner.com/blogs/exception-linq-to-entities-does-not-recognize-the-method-tostring - Dimitri
这是LINQ to SQL还是LINQ to EF?在LINQ to SQL中,ToString对我来说似乎可以静态或动态地工作。 - NetMage
如果类型是数字,您可以尝试使用 SqlFunctions.StringConvert - NetMage
@NetMage 这是以 IQueryable 形式的 Linq to SQL。如果我先调用 ToList()ToEnumerable(),它可能会起作用,但我不想在内存中处理这个。我尝试在动态表达式(以字符串形式编写)中使用 SqlFunctions.StringConvert,但它给我一个错误。现在我只能检查它是否为数字,我使用 == ,如果它是字符串,我使用 .Contains()。这不是我想要的。它的行为不像 Like 运算符。 - Alvin Stefanus
你正在使用EF的哪个版本? - Stef Heyenrath
也许 DbFunctions.Like() 可以帮助你。 - kapsiR
4个回答

14
如果您使用 System.Linq.Dynamic.CoreEF 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");

我没有使用EF Core。Contains()只能被字符串类型的对象使用,否则会抛出错误。 - Alvin Stefanus

4
这里的问题在于,IQueryable 是在 SQL 服务器上运行而不是在 C# 中运行,所以 SQL 服务器对 .toString() 方法一无所知。 因此,Like operator 自身对字符串起作用。在 SQL Server 中,它适用于 nvarchar 和 varchar 数据类型。 如果您能告诉我更多关于您的问题和您想要实现的内容,我可以给您一个示例。 可以提供一个样本。

0

你已经有了在数据库中运行并与字符串一起使用的 Linq 中的“Like”,它被称为“IndexOf”:

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

根据MSDN: IndexOf(string) '如果找到了该字符串,则返回值的基于零的索引位置;如果未找到,则返回-1。如果value为空,则返回值为0。'

0

我想为我的数据制作一个通用的排序器。

与其修复'调用问题', 通用的方式应该使用泛型,例如

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”似乎是合理的,但存在通用和规范形式exists


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接