【问题标题】:Dynamic LINQ - Unable to convert between GUID and string动态 LINQ - 无法在 GUID 和字符串之间转换
【发布时间】:2012-02-24 19:21:59
【问题描述】:

我正在动态构建一个 LINQ 语句。我正在构建的 LINQ 语句纯粹用于 WHERE 子句。

string[] values = GetPropertyValues(); 
string propertyName = GetPropertyName();

string clause = string.Empty;
if (values.Length > 0)
  clause = propertyName + "==\"" + values[0] + "\"";

据我所知,我的 LINQ 查询看起来是正确的。但是当它被执行时,我收到一条错误消息:

运算符 '==' 与操作数类型 'Guid?' 不兼容和'字符串'

我该如何解决这个问题?

谢谢!

【问题讨论】:

标签: c# linq


【解决方案1】:

不带参数对我有用

"Id.Equals(Guid(\"D243372F-7ED0-40E6-B93D-6165F7521C29\"))"

使用“价值”不起作用。出现错误

"{No property or field 'Value' exists in type 'Guid' (at index 3)}"

【讨论】:

    【解决方案2】:

    要与动态 linq 进行 GUID 比较,请使用查询属性和提供的示例中的 Equals() 方法。

    var items = new[]
                {
                    new { Id = Guid.Empty },
                    new { Id = Guid.NewGuid() },
                    new { Id = Guid.NewGuid() }
                };
    
    var result = items.AsQueryable()
        .Where("Id.Equals(@0)", Guid.Empty)
        .Any();
    

    【讨论】:

      【解决方案3】:

      对于一个可以为空的值,这样的事情会起作用:

      clause = "Id.Value.ToString()==\"a\""; /* Id is of type Guid? */
      

      但这显然是一个相当具体的案例。

      Albahari 的 PredicateBuilder 可能是一个更好的解决方案。

      【讨论】:

      • 也许 GetPropertyName() 返回一个非字符串对象。所以我猜应该是 string propertyName = GetPropertyName().ToString();
      • @Love:我认为它实际上以字符串形式返回属性名称(例如"Id")。这基本上就是构建动态where 子句所需的内容(将某个属性的值与不同的值进行比较)。但是当动态 LINQ 编译表达式时,它无法将Id(即Nullable<Guid>)的值与String 进行比较。
      • 你刚刚拯救了我的一天。我现在可以和我的孩子一起去野餐了:D
      【解决方案4】:

      听起来 GetPropertyName() 返回的属性是 Guid 类型(我从错误中猜测),但您正试图将其与您声明为字符串的 values[0] 的内容进行比较。

      Dynamic Linq 允许您在 where 子句中定义参数,以便您可以这样做

      string clause = propertyName + "= @1";
      LambdaExpression expr = Dynamic.ParseLambda( typeof(YourType), typeof(bool), clause, values[0]);
      

      其中YourType 是源IQueryable 中项目的类型。因此,例如,如果您的源查询是 IQueyable<Customer>,那么 YourType 将是 Customer。无论propertyName 指示的属性类型是什么,这都会起作用。

      当它进行解析时,Dynamic Linq 会在 YourType 和 propertyName 上使用反射来确定 lambda 表达式的类型参数应该是什么。你得到的 lambda 表达式就是你应该用作.Where() 扩展方法的参数。

      【讨论】:

      • +1 这是正确的答案(虽然值得一提的是Where扩展方法也支持命名参数,所以不需要调用这个静态方法)。 OP 正在做的事情和 this(我想指出)之间的实际区别是,在这种情况下, value 不必再是字符串了。它可以是一个实际的Guid 实例。在这种情况下,GetPropertyValues() 需要返回实际值,而不是它们的字符串表示形式。
      • 完全正确。 GetPropertyValues 需要是 object[] 类型而不是 string[]。
      【解决方案5】:

      如果您不想将 guid 作为参数传递,可以将其用于字符串和 guid 比较:

      clause = "Id.Value.Equals(Guid(\"" + values[0] + "\"))";
      

      这是可行的。

      ...或者在您的示例中:

      clause = propertyName + ".Value.Equals(\"" + values[0] + "\")";
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-01
        • 1970-01-01
        • 2012-09-30
        • 2011-11-06
        • 2021-09-13
        • 2010-11-29
        • 1970-01-01
        相关资源
        最近更新 更多