我正在尝试进行动态 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);
但我最终遇到了两个问题:
第一个问题是我的
whereConditions
字符串是这样形成的:CARD_NUMBER == @cardNumber
但我收到以下错误:
No property or field 'cardNumber' exists in type 'CARD'
让我相信它无法在对象参数和用于执行查询的字符串之间建立联系。
如您所见,我有一个参数列表。这是因为我无法确定用户将选择多少个参数。所以每次用户输入一个新的搜索字段时,我都必须创建一个新的 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--;
}
}
}
它有效。这不是使它工作的优雅方式,但我可以按照我想要的方式验证字段,为此,我最后很感激。