Arm*_*and 8 c# .net-core asp.net-core-webapi asp.net-core-2.0 ef-core-2.0
我编写了一些代码来制作动态表达式来过滤我的分页。我正在尝试制作 EF Core 内置函数的动态表达式以进行搜索 ( EF.Functions.Like
)。
我尝试过像bottom这样的方法,但它是一个扩展方法,调用该方法时不使用第一个参数。我不知道如何遵循==> Ef => Function => Like的方式。
该方法应该像这样使用=>Ef.Functions.Like("Property to search", "%Some Pattern")
var likeMethod = typeof(DbFunctionsExtensions)
.GetMethods()
.Where(p => p.Name == "Like")
.First();
string pattern = $"%{finalConstant}%";
ConstantExpression likeConstant = Expression.Constant(pattern,typeof(string));
// the member expression is the property expression for example p.Name
var likeMethodCall = Expression.Call(method: likeMethod, arguments: new[] { memberExpression, likeConstant });
var searchLambda = Expression.Lambda<Func<T, bool>>(likeMethodCall, parameter);
query = query.Where(searchLambda);
Run Code Online (Sandbox Code Playgroud)
但它抛出异常说
为调用方法“Boolean Like(Microsoft.EntityFrameworkCore.DbFunctions, System.String, System.String)”提供的参数数量不正确\r\n参数名称: 方法
我根据这篇文章实现了动态搜索\n .NET Core Npgsql.EntityFrameworkCore ILikeExpression \n这就是我所做的:
\n我实现了 [Searchable] 属性,用它来标记将执行搜索的属性。属性仅是 string 类型,如果有必要我可以解释如何搜索 long 和 int 类型的属性。
\n[AttributeUsage(AttributeTargets.Property)]\npublic class SearchableAttribute : Attribute\n{\n}\n
Run Code Online (Sandbox Code Playgroud)\n为 IQueryable 创建了一个扩展,它从搜索中获取输入字符串,并根据指定的属性实现 Like 函数
\npublic static class QueryableExtension\n{\n public static IQueryable<TEntityDto> ExecuteQueryFilter<TEntityDto>(this IQueryable<TEntityDto> queryable, string query)\n where TEntityDto : class, IEntityDto\n {\n // If the incoming request is empty, skip the search\n if (string.IsNullOrEmpty(query))\n {\n return queryable;\n }\n\n // We get all properties with type of string marked with our attribute\n var properties = typeof(TEntityDto).GetProperties()\n .Where(p => p.PropertyType == typeof(string) &&\n p.GetCustomAttributes(typeof(SearchableAttribute), true).FirstOrDefault() != null)\n .Select(x => x.Name).ToList();\n\n // If there are no such properties, skip the search\n if (!properties.Any())\n {\n return queryable;\n }\n\n // Get our generic object\n ParameterExpression entity = Expression.Parameter(typeof(TEntityDto), "entity");\n\n // Get the Like Method from EF.Functions\n var efLikeMethod = typeof(DbFunctionsExtensions).GetMethod("Like",\n BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic,\n null,\n new[] { typeof(DbFunctions), typeof(string), typeof(string) },\n null);\n\n // We make a pattern for the search\n var pattern = Expression.Constant($"%{query}%", typeof(string));\n\n // Here we will collect a single search request for all properties\n Expression body = Expression.Constant(false);\n\n foreach (var propertyName in properties)\n {\n // Get property from our object\n var property = Expression.Property(entity, propertyName);\n\n // \xd0\xa1all the method with all the required arguments\n Expression expr = Expression.Call(efLikeMethod,\n Expression.Property(null, typeof(EF), nameof(EF.Functions)), property, pattern);\n\n // Add to the main request\n body = Expression.OrElse(body, expr);\n }\n\n // Compose and pass the expression to Where\n var expression = Expression.Lambda<Func<TEntityDto, bool>>(body, entity);\n return queryable.Where(expression);\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\nDto 对象本身如下所示:
\npublic class CategoryDto : IEntityDto\n{\n public long Id { get; set; }\n\n [Searchable]\n public string Name { get; set; }\n\n [Searchable]\n public string IconKey { get; set; }\n\n public long UploadId { get; private set; }\n\n [Searchable]\n public string UploadFileName { get; set; }\n\n [Searchable]\n public string CreatedBy { get; set; }\n public DateTime Created { get; set; }\n}\n
Run Code Online (Sandbox Code Playgroud)\n我在 100 万条记录上测试了这种搜索方法,其中对象名称为一到五个单词。搜索过程非常快。这里的性能优势是表达式在数据库端转换为 LINQ to SQL
\n正如评论中提到的,您需要包含EF.Functions作为第一个参数:
var likeMethodCall = Expression.Call(likeMethod, new []
{
Expression.Property(null, typeof(EF).GetProperty("Functions")),
memberExpression,
likeConstant
});
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
5619 次 |
最近记录: |