簡體   English   中英

EF Core - 按字符串搜索屬性

[英]EF Core - search properties by string

我有一個包含幾百列的表,並且從我的客戶端我將多個“搜索”對象傳遞給用於查詢該表的服務器。 每個搜索對象都包含一個搜索詞,以及與之匹配的屬性名稱。

我不確定如何在此處使用反射來使用 EF Core 查詢屬性。 我嘗試了以下方法,但它不喜歡它。

var prop = <ENTITYTYPE>.GetProperty(search.Property);

query = context.<ENTITY>.Where(x => (string)prop.GetValue(x) == search.SearchTerm);

我在想我可能必須構建一個原始 SQL 查詢,但我很想知道是否有一種方法可以讓 EF Core 自己創建查詢。 當我在上面執行.ToList()時,它表示無法翻譯查詢。

任何幫助,將不勝感激!

這是基本的認識,應該會推動你朝着正確的方向前進:

public static IQueryable<T> AddFilter<T>(IQueryable<T> query, string propertyName, string searchTerm)
{
    var param = Expression.Parameter(typeof(T), "e");
    var propExpression = Expression.Property(param, propertyName);
    
    object value = searchTerm;
    if (propExpression.Type != typeof(string))
        value = Convert.ChangeType(value, propExpression.Type);

    var filterLambda = Expression.Lambda<Func<T, bool>>(
        Expression.Equal(
            propExpression,
            Expression.Constant(value)
        ),
        param
    );

    return query.Where(filterLambda);
}

此方法應該適用於單實例實體。

public IQueryable<T> GetBySearchTerm(IQueryable<T> queryable, string search)
{
    void GenerateLambda<T>(IProperty columnProp, MethodInfo methodInfo, List<Expression<Func<T, bool>>> expressions)
    {
        if (columnProp.ClrType == typeof(string))
        {
            // Define the parameter
            ParameterExpression xParam = Expression.Parameter(typeof(T), "x");
            // Create the expression representing what column to do the search on
            MemberExpression colExpr = Expression.Property(xParam, columnProp.Name);
            // Create a constant representing the search value
            ConstantExpression constExpr = Expression.Constant(search);
            // Generate a method body that represents "column contains search"
            MethodCallExpression lambdaBody = Expression.Call(colExpr, methodInfo, constExpr);
            // Convert the full expression into a useable query predicate
            Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(lambdaBody, xParam);
            expressions.Add(lambda);
        }
    }

    T thisEntityBaseModel = new T();
   
    IEntityType set = _dbContext.Model.GetEntityTypes().First(x => x.ClrType.Name.ToUpper() == thisEntityBaseModel.ModelName.ToUpper());
    List<Expression<Func<T, bool>>> predicateArray = new List<Expression<Func<T, bool>>>();

    MethodInfo containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
    
    foreach (IProperty columnProp in set.GetProperties())
    {
        GenerateLambda(typeof(T), columnProp, containsMethod, predicateArray);
    }


    // This performs an "OR" method on the predicates, since by default it wants to do "AND"
    var predicate = PredicateBuilder.False<T>();
    foreach (Expression<Func<T, bool>> expression in predicateArray) {
        predicate = predicate.Or(expression);
    }

    // Process the ors
    return (queryable.Where(predicate));
}

不推薦使用,請參閱我在下面嘗試過的示例的評論,它對我有用

private void Test()
{

    Type myType = typeof(AktivEvents);

    PropertyInfo myPropInfo = myType.GetProperty("AutoReplyMessage");

    Func<AktivEvents, bool> func = (e) => (string)myPropInfo.GetValue(e) == "asdasd";


    var query = _dbService.AktivEvents.GetAll()
        .Where(func)
        .ToList();
}

它顯然很臟,但這個想法很有效,有依賴關系

    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.0" />

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM