简体   繁体   English

我可以在LINQ Where子句中使用属性吗?

[英]Can I Use a Property in a LINQ Where Clause?

First off, I apologize if the title of this is trash. 首先,如果这个标题是垃圾桶,我深表歉意。 I'm new to C# and ASP and I'm not even sure how to ask this question. 我是C#和ASP的新手,我什至不知道如何问这个问题。

I'm trying to incorporate a search feature to my web page. 我正在尝试将搜索功能合并到我的网页中。 I have a text box that will take a search term that the user wants. 我有一个文本框,其中包含用户想要的搜索词。 A drop down will select which FIELD of my database table it will search in. So if there are last names and first names, the user can choose which to search in. I have a property called SearchField{get; 下拉列表将选择要在数据库表中搜索的字段。因此,如果有姓和名,用户可以选择要搜索的名字。我有一个名为SearchField {get;的属性。 set;} that will hold the value the user selects in the drop down but when I try to use this in my LINQ statement along with the Contains(blah) I get an error. set;},它将保留用户在下拉菜单中选择的值,但是当我尝试在LINQ语句中将其与Contains(blah)一起使用时,出现错误。

I've tried very little since I really don't know much about C# or what the error is even telling me. 由于我对C#甚为不了解,甚至错误告诉我什么,所以我做了很少的尝试。

cshtml file cshtml文件

<form>
    <p>
        <select asp-for="SearchField" class="form-control">
            <option value="FirstName">First Name</option>
            <option value="LastName">Last Name</option>
            <option value="Salary">Salary</option>
            <option value="Gender">Gender</option>
            <option value="Department">Department</option>
            <option value="Location">Location</option>
            <option value="Performance">Performance</option>
        </select>
        Search: <input type="text" asp-for="SearchString" class="form-control" />
        <input type="submit" value="Filter" class="form-control" />
    </p>
</form>

cs file CS文件

   [BindProperty(SupportsGet = true)]
   public string SearchField { get; set; }

   public async Task OnGetAsync()
    {
        var employees = from x in _context.Employee
                     select x;
        if (!string.IsNullOrEmpty(SearchString))
        {
            employees = employees.Where(x => x.SearchField.Contains(SearchString));
        }
        Employee = await employees.ToListAsync();
    }

Error: Object does not contain a definition for 'Contains' and the best known extension method overload Queryable.Contains..... requires a receiver of type IQueryable 错误:对象不包含“包含”的定义,并且最著名的扩展方法重载Queryable.Contains .....需要类型为IQueryable的接收器

You can use reflection in C# to get the property based on your SearchField and compare the value of the property with your SearchString. 您可以在C#中使用反射来获取基于SearchField的属性,并将该属性的值与SearchString进行比较。 https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/reflection https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/reflection

In your case: 在您的情况下:

public async Task OnGetAsync()
    {
        var employees = from x in _context.Employee
                     select x;
        if (!string.IsNullOrEmpty(SearchString))
        {
            employees = employees.Where(x => x.GetType().GetProperty(SearchField).GetValue(x, null).ToString() == SearchString);
        }
        Employee = await employees.ToListAsync();
    }

You could also use String.Contains in the following way: 您还可以按以下方式使用String.Contains:

employees = employees.Where(x => x.GetType().GetProperty(SearchField).GetValue(x, null).ToString().Contains(SearchString, StringComparison.InvariantCultureIgnoreCase));

You need to dynamically create Expression tree which will be filtering your table and return only matched values. 您需要动态创建表达式树,该树将过滤表并仅返回匹配的值。

Here is what you need for string properties (it's deliberately spread over many lines): 这是字符串属性所需要的(故意分布在多行上):

// Expression to construct: (Employee parameter) => parameter.GetPropertyValue(searchField).Contains(SearchValue)
var parameter = Expression.Parameter(typeof(Employee));
var employeePropertyValue = Expression.Property(parameter, searchField);

var constainsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
var contains = Expression.Call(employeePropertyValue, containsMethod, Expression.Constant(searchString));
var whereCondition = (Expression<Func<Employee, bool>>)Expression.Lambda(contains, parameter);

// filtering
employees = employees.Where(whereCondition);

For non-string properties, you will need to construct different condition depending of property type (for example Enum property will be stored in database in integer so you need to convert SearchValue to Gender and use Expression.Equal) 对于非字符串属性,您将需要根据属性类型构造不同的条件(例如,Enum属性将以整数形式存储在数据库中,因此您需要将SearchValue转换为Gender并使用Expression.Equal)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM