【问题标题】:Entity Framework 4: convert a string condition to a lambda expression?实体框架 4:将字符串条件转换为 lambda 表达式?
【发布时间】:2011-05-03 14:42:51
【问题描述】:

我想接受来自客户端的 where 条件的字符串数组,例如 field == value。 在构造函数中创建一个可以接受字符串并输出 lambda 表达式来表示 Where 子句的规范对象会非常好。例如,我可以执行以下操作:

var myCondition = new Specification<Product>( myStringArrayOfConditions); 
var myProducts = DB.Products.Where( myCondition);

你怎么能把"name == Jujyfruits"变成
DB.Products.Where(p =&gt; p.name == "JujyFruits")

【问题讨论】:

  • 为什么不能将 lambda 传递给方法,所以不要传递字符串 .Where("name == Jujyfruits") 而是传递 .Where(x => x.name == “Jujyfruits”)?我真的不知道你想做什么。
  • 如果“规范”(where子句)来自客户端,则为字符串形式。我需要将其转换为 EF 可以理解的内容,通常是 lambda 表达式。

标签: c# c#-4.0 entity-framework-4


【解决方案1】:

你可以使用

  • 反射从字符串name获取属性Product.name
  • LINQ Expression 类手动创建 lambda 表达式。

请注意,以下代码示例仅适用于 Equals (==) 操作。但是,它也很容易推广到其他操作(按空格分割、解析运算符并选择适当的表达式而不是 Expression.Equal)。

    var condition = "name == Jujyfruits";

    // Parse the condition
    var c = condition.Split(new string[] { "==" }, StringSplitOptions.None);
    var propertyName = c[0].Trim();
    var value = c[1].Trim();

    // Create the lambda
    var arg = Expression.Parameter(typeof(Product), "p");
    var property = typeof(Product).GetProperty(propertyName);
    var comparison = Expression.Equal(
        Expression.MakeMemberAccess(arg, property),
        Expression.Constant(value));
    var lambda = Expression.Lambda<Func<Product, bool>>(comparison, arg).Compile();

    // Test
    var prod1 = new Product() { name = "Test" };
    var prod2 = new Product() { name = "Jujyfruits" };
    Console.WriteLine(lambda(prod1));  // outputs False
    Console.WriteLine(lambda(prod2));  // outputs True

关于构造函数:由于Func&lt;T, TResult&gt; 是密封的,因此您不能从中派生。但是,您可以创建一个implicit conversion operator,将Specification&lt;T&gt; 转换为Func&lt;T, bool&gt;

【讨论】:

  • 所以你可以做类似 Products.Where( p => lambda(p))?
  • @Dr. Zim:其实Products.Where(lambda) 就足够了。
  • 如果您打算走这条路,请考虑缓存委托(var lambda)。编译表达式树会对性能造成一定的影响,您绝对不想在每次搜索查询之前都这样做。
  • @AnteSim:这取决于你如何定义“合理”。在我的机器上编译上面示例中的 lambda 大约需要 5 毫秒。我猜搜索的数据库查询部分需要更长的时间......
  • @Heinzi:当他调整这段代码来过滤基于多个属性的搜索时会发生什么?单独来看,您的代码很好。但您只需要注意,如果需要,这是一个优化点。
【解决方案2】:

我们最近从 VS2008 示例项目中发现了 Dynamic LINQ 库。非常适合将基于字符串的“Where”子句转换为表达式。

This link will get you there.

【讨论】:

  • 它肯定在 where 子句中使用了一个字符串。这是一个很好的答案。但是,它会在更改数据类型时产生副作用。
【解决方案3】:

您需要将搜索词转换为谓词。尝试以下方法:

string searchString = "JujyFruits";
Func<Product, bool> search = new Func<Product,bool>(p => p.name == searchString);

return DB.Products.Where(search);

【讨论】:

  • 是否有办法绕过大 switch 语句测试 Product 的每个属性的名称?您能否获取 Product 的“原始”属性列表,针对字段魔术字符串进行测试,并构造一个将 p.name 表示为魔术字符串的 lambda 表达式?
  • 嗯,我不确定这是微不足道的。看到这个问题:stackoverflow.com/q/714799/68432
  • linqspecs.codeplex.com 与您的回答非常相似,这强化了您的方法可能是使规范成为一等公民的普遍接受的方法。
猜你喜欢
  • 2019-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多