选择列,其中一个列包含值是可能的吗?在linq中

本文关键字:linq 一个 选择 包含值 | 更新日期: 2023-09-27 18:15:41

查询其中一列包含值的最佳方法是什么?

这是我的代码:

public JsonResult FindCustomer(string value)
{
    var result= new SelectList(db.Customers.Where(t => (t.PersonalMail.Contains(value) ||
    t.BusinessMail.Contains(value)
    || t.ContactName.Contains(value) ||
    t.BusinessName.Contains(value) || t.Phone.Contains(value) ||
    t.DirectPhone.Contains(value)), "ID", "PersonalMail");
    return Json(jj);
}

也许可以这样做:

var result= new SelectList(db.Customers.Where(t => (Each column).Contains(value)), "ID", "PersonalMail");

选择列,其中一个列包含值是可能的吗?在linq中

public JsonResult FindCustomer(string value)
{
    var Customers = db.Customers.ToList();
    var result = new SelectList(db.Customers.Where(t =>
        t?.GetType().GetProperties().Any(x => //for all columns of a row where...
            (x.PropertyType==typeof(string)) && // it does have the same type
            x.GetValue(t, null) != null && // the value should not be null
             x.GetValue(t, null).ToString().Contains(value)) // the value should be equal
        ?? false), // if t is null, than skip it
        "ID", "PersonalMail");
    return Json(jj);
}

就可以了。如果要排除某些列,请将它们添加到ANY子句:

.Any(x =>  x.GetValue(t, null) != null && !x.Name.Equals("BusinessMail") && (x.PropertyType==typeof(string)) && x.GetValue(t, null).ToString().Contains(value))

选择包含该值的第一个属性的值,在"PersonalMail")后面添加以下内容:

.Select(t=>t.GetType().GetProperties().First(x=> // get the first porperty
    x.GetValue(t, null).Equals(value) // where the value equals the searched one
 ).GetValue(t, null)); // And select the value of that property.

如果您确实想获得属性而不是值,则删除.GetValue(t, null)。您也可以使用Where而不是Any,并将返回包含该值的所有属性的列表。(注意,它将返回一个充满PropertyInfo的集合!)

不确定这样做是否更好或值得,但是(假设所有类型都是相同的)您可以这样做:

var result =
    new SelectList (
        db
        .Customers
        .Where (t => new[] {
            t.PersonalMail,
            t.BusinessMail,
            t.ContactName,
            t.BusinessName
            t.Phone,
            t.DirectPhone
        }.Any (s => s.Contains (value))), "ID", "PersonalMail");

但是我认为最好在某个地方(可能在t来自的类中)有一个方法来利用像

这样的东西
bool CheckContains (TypeOfT t, string value)
{
    return t.PersonalMail.Contains (value)
        || t.BusinesMail.Contains (value)
        || t.ContactName.Contains (value)
        || t.BusinessName.Contains (value)
        || t.Phone.Contains (value)
        || t.DirectPhone.Contains (value);
}
// ...
var result = new SelectList (db.Customers.Where (t => CheckContains (t, value)), "ID", "PersonalMail");

如果你想让它更短,你可以试试:
db.Customers.Where(t => (t.PersonalMail + t.BusinesMail + t.ContactName).Contains(value)
但这可能不是效率

您可以使用

var result = new SelectList((from t in db.Customers
                             let values = new[]
                             {
                                    t.PersonalMail,
                                    t.BusinessMail,
                                    t.ContactName,
                                    t.BusinessName,
                                    t.Phone,
                                    t.DirectPhone
                             }
                             where values.Any(v => v.Contains(value))
                             select t), "ID", "PersonalMail");

您可以使用反射来构建适当的表达式。添加以下using语句:

using System.Linq.Expressions;
using static System.Linq.Expressions.Expression;

像这样:

static Expression<Func<Customer, bool>> ExpressionBuilder(string phrase) {
    //We are trying to set up the equivalent of this:
    //  x => x.PersonMail == phrase || x.BusinessMail == phrase || x.ContanctName == ...
    //The lambda expression has a single parameter
    //  x =>
    //In the body of the lambda, for each string property on Customer, we want to call the 
    //property on the parameter, and then check if it is equal to the phrase
    //  x.PersonMail == phrase
    //We then want to combine each result into an ||
    //  x.PersonMail == phrase || x.BusinessMail == phrase ...
    //Define an expression representing the parameter
    var prm = Parameter(typeof(Customer));
    //Get all the string properties
    var stringProps = typeof(Customer).GetProperties()
        .Where(x => x.PropertyType == typeof(string))
        //For each property, create an expression that represents reading the property, and 
        //comparing it to phrase as a constant (as if we had written the literal value into 
        //the query)
        .Select(x => Equal(MakeMemberAccess(prm, x), Constant(phrase)));
    //Combine the equals expressions using ||
    Expression expr = stringProps.Aggregate((prev, x) => Or(prev, x));
    //Wrap the body in a lambda expression of the appropriate type
    return Lambda<Func<Customer, bool>>(expr, prm);
}

然后,你可以这样调用它:

//qry is IQueryable<Customer>
qry = qry.Where(ExpressionBuilder("test"));