1

我正在尝试进行动态 linq 查询,该查询将根据字符串检查值。

首先,这是查询:

objQry = from o in m_Db.OBJECTS.Where(whereConditions)
                      select o;

if(!objQry.Any())
{
    return null;
}

whereConditions变量是我构建并作为参数传递的字符串,以找出我需要的值。以下是有效字符串的示例:

OBJ_NAME == \"Sword\" and OBJ_OWNER == \"Stan\" 这将返回名称为“Sword”且所有者为“Stan;

OBJ_COLOR == \"Blue\" OR OBJ_COLOR == \"Red\" 这将返回任何颜色为蓝色或红色的项目。

到那里为止,我很好,但现在我有一个问题:我需要检查一个十进制字段。所以我试过这个字符串:

OBJ_NUMBER == 1

但是即使存在 OBJ_NUMBER 值为 1 的对象,查询也会返回 null。它是小数。如何指示他们需要检查十进制值的查询?

**** 编辑 ****

我试图“修改”传递的值,使其看起来像这样:

"CARD_NUMBER == Convert.ToDecimal(1)"

现在我有另一种错误告诉我:

LINQ to Entities does not recognize the method 'System.Decimal ToDecimal(Int32)' method, and this method cannot be translated into a store expression.

任何线索任何人?我仍在寻找一种方法来做到这一点。谢谢!

编辑 2

您可以通过查看这个问题来了解我的代码是如何形成的。

让我们回到这个问题。我想检查十进制值。假设 OBJ_NUMBER 是一个十进制字段。

使用Dynamic Linq,我尝试读取十进制字段。假设我想获取每个数字为 1.27 的对象。然后该whereConditions字段的形状将如下所示:

OBJ_NUMBER == 1.27

但后来我会得到一个Invalid real literal '1.27'错误。我不知道为什么。

所以我尝试了 Gert Arnold 的解决方案并改为这样做:

decimal bDecimal = decimal.Parce(valueToParse);

param = new ObjectParameter("cardNumber", typeof(decimal)) { Value = bDecimal };

valuesToUse.Add("CARD_NUMBER == @cardNumber");

listParams.Add(param);

但我最终遇到了两个问题:

  1. 第一个问题是我的whereConditions字符串是这样形成的:

    CARD_NUMBER == @cardNumber

    但我收到以下错误:

    No property or field 'cardNumber' exists in type 'CARD'

    让我相信它无法在对象参数和用于执行查询的字符串之间建立联系。

  2. 如您所见,我有一个参数列表。这是因为我无法确定用户将选择多少个参数。所以每次用户输入一个新的搜索字段时,我都必须创建一个新的 ObjectParameter 并将其存储在一个列表中。以下是我之后尝试做的事情:

    ObjectParameter[] arrayParameters = listParams.ToArray(); // Convert the list to an array

然后,当我尝试进行查询时:

cardQry = from c in mDb.CARD.Where(whereConditions, arrayParameters)
                               select c;

但无济于事。

结果

根据下面回答的问题,我开发了一些“糟糕”但功能强大的东西。

首先,我忽略了每个小数字段,因为我永远无法使用动态 linq 访问它们。相反,我这样做:

var valuesToParse = keyValuePair.Value.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);

// Here I parse the value and, if that's the case, the symbol.

decimal baseValue = decimal.Parse(valuesToParse[0]); 

if (valuesToParse.Count() > 1)
{
    string baseMethod = valuesToParse[1];

    if (baseMethod == ">" || baseMethod == ">=")
    {
        if (baseMethod == ">=")
        {
            baseValue--;
        }

        // The list is actually like this: Dictionary<string, object> list = new Dictionary<string, object>();
        list.Add("low", baseValue);

        // I kind of activate a tag telling me that the user is looking for a higher value.
        cardHigher = true;
    }
    else
    {
        if (baseMethod == "<=")
        {
            baseValue++;
        }


        list.Add("low", baseValue);

        cardLower = true;
    }
}
else
{
    //lowParam = new ObjectParameter("dec", typeof(decimal)) { Value = baseValue };

    list.Add("low", baseValue);
}

cardNumberActivated = true;

最后,当我得到对象列表时,我这样做:

if (list.Count > 0)
{

    (example)
    if (cardNumberActivated)
    {
        if (cardHigher)
        {
            q = mDb.CARD.Where("CARD_NUMBER >= @0", list["low"]).ToList();
        }
        else if (cardLower)
        {
            q = mDb.CARD.Where("CARD_NUMBER <= @0", list["low"]).ToList();
        }
        else
        {
            q = mDb.CARD.Where("CARD_NUMBER == @0", list["low"]).ToList();
        }
    }
}

// Here we get the orinalData with the basic filters.
listToReturn.AddRange(cardQry);

if (q != null)
{
    //listToReturn.AddRange(q);
    for (int i = 0; i < listToReturn.Count; i++)
    {
        var priceList1 = listToReturn[i];
        if (!q.Any(_item => _item.CARD_NUMBER == priceList1.CARD_NUMBER))
        {
            listToReturn.RemoveAt(i);
            i--;
        }
    }
}

它有效。这不是使它工作的优雅方式,但我可以按照我想要的方式验证字段,为此,我最后很感激。

4

1 回答 1

1

您不应该使用内联谓词值构建查询字符串。请改用参数。然后也可以指定类型:

var whereConditions= "it.CARD_NUMBER = @cardNumber";
var param = new ObjectParameter("cardNumber", typeof(decimal)) { Value = 1 };
objQry = from o in m_Db.OBJECTS.Where(whereConditions, param);

编辑

我不知道您的代码中有什么不起作用。这只是从我自己的一个项目中派生的一段随机工作代码:

var param1 = new ObjectParameter("dec", typeof(decimal)) { Value = 90000m };
var param2 = new ObjectParameter("int", typeof(int)) { Value = 90000 };
var q = ValueHolders.Where("it.DecimalValue >= @dec OR it.IntegerValue > @int",
                    param1, param2).ToList();

请注意,param1, param2它也可能是一个ObjectParameter.

于 2013-04-17T21:51:53.247 回答