【问题标题】:Use string as field name in LINQ在 LINQ 中使用字符串作为字段名
【发布时间】:2012-06-26 09:54:38
【问题描述】:

看看下面的代码。我想用参数field 中收到的字段名称替换USERNAME。此方法必须能够对多个字段进行一些搜索。

谢谢,

public void Searching(string field, string stringToSearch)
{
    var res = 
        from user in _dataContext.USERs where 
        user.USERNAME.Contains(stringToSearch)
        select new 
        {
          Id = user.ID,
          Username = user.USERNAME
        };

}

【问题讨论】:

  • 是 LINQ to SQL 还是 LINQ to Objects?

标签: c# linq linq-to-sql linq-to-objects


【解决方案1】:

你需要忘记匿名类型,也许改用Tuple<int,string>;但是:怎么样:

IQueryable<Foo> source = // YOUR SOURCE HERE
      // in-memory dummy example:
      // source = new[] {
      //    new Foo {Id = 1, Bar = "abc"},
      //    new Foo {Id = 2, Bar = "def"}
      // }.AsQueryable();

string field = "Bar";
string stringToSearch = "d";
var param = Expression.Parameter(typeof (Foo), "x");
var predicate = Expression.Lambda<Func<Foo, bool>>(
    Expression.Call(
        Expression.PropertyOrField(param, field),
        "Contains", null, Expression.Constant(stringToSearch)
    ), param);
var projection = Expression.Lambda<Func<Foo, Tuple<int, string>>>(
    Expression.Call(typeof(Tuple), "Create", new[] {typeof(int), typeof(string)},
        Expression.PropertyOrField(param, "Id"),
        Expression.PropertyOrField(param, field)), param);
Tuple<int,string>[] data = source.Where(predicate).Select(projection).ToArray();

【讨论】:

  • 该死,你的速度快了一分钟……而我没有时间测试我的。希望它仍然有效:)
  • 所以这是可能的,但是查询不同的列是一个好习惯吗?我们不应该把他们分开 Gravell 先生吗?我真的很欣赏你的工作。
  • @RoboLover 你是什么意思“划分他们”?作为基本的“给我找一些匹配项;我想要唯一 ID 和匹配的东西”,这不是不合理的
  • Kris 说This methode must be able to make some search several field. 如果我没有误解,他想发送一个参数,该参数将是查询中的列名。例如,用户名、手机、地址。我要问的是不应该用三个不同的查询而不是用这样的方法来完成吗?如果我误解了,请原谅我。
  • @RoboLover:如果他想同时查询多个列,那么整个问题的措辞是错误的……
【解决方案2】:

事实上,可以使用 Expression API:

public void Searching(Expression<Func<User,string>> field, string stringToSearch)
{

   var call = Expression.Call(field.Body, typeof (string).GetMethod("Contains"), new[] {Expression.Constant(value)});
   Expression<Func<User, bool>> exp = Expression.Lambda<Func<User, bool>>(Expression.Equal(call, Expression.Constant(true)), field.Parameters);


    var res =  _dataContext.USERs.Where(exp).Select(u=>new { id= u.ID, Username = u.USERNAME});

}

【讨论】:

  • 投影(Select需要是自定义表达式
  • @MarcGravell:为什么?它是完全输入的!
  • "我想将USERNAME替换为参数field中的接收字段名" - 因此u.USERNAME 不存在;应该是u.SomethingElseHere。不过,我确实喜欢您将传入表达式用于基体和参数!
  • 哦,我没有抓住那部分要求:(
  • @Kris-I:LambdaExpression 上应该有一个 Body 成员。
【解决方案3】:

你正在尝试的东西是不可能的。但是,您可以使用dynamic linq library 来实现您想要的

【讨论】:

  • 如果我们去掉匿名类型(也许使用元组代替),它可能的;确实,如果动态 LINQ 库可以做到,那一定是可能的;正在研究一个例子......
  • @MarcGravell 等待样本,其他样本不工作,编译错误和其他
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-30
  • 2011-07-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多