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

时间:2016-11-01 09:48:07

标签: c# linq

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

这是我的代码:

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");

5 个答案:

答案 0 :(得分:1)

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填充的集合!)

答案 1 :(得分:0)

不确定它更好还是值得,但(假设所有类型相同)你可以这样做:

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");

答案 2 :(得分:0)

您可以使用

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");

答案 3 :(得分:0)

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

答案 4 :(得分:0)

您可以使用反射来构建适当的表达式。添加以下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"));