从具有不同值的字符串构建查询

本文关键字:字符串 构建 查询 | 更新日期: 2023-09-27 18:09:25

我正在构建一个MVC应用程序,在这个应用程序中,我需要根据用户使用的过滤器获得对象列表。

所以我可能会得到一个这样的字符串:
*OBJNAME=[SWORD][OF][THOUSAND][TRUTHS]*OBJTYPE=[ARTEFACT]*OBJNUMBER=[28]*COST=[9]+<*POWER=[3]+>=*RATING=[4]+<*OWNER=[WRIGHT][STAN]*OBJSET=[WORLD OF WARCRAFT]*RARITY=[LEGENDARY]*ADDCOST=[6QGBA]*OBJCOLOR=[ALL]

每个*都是我在构建字符串时引入的标签,这样我就可以在DAL类中单独识别每个属性:

public List<ObjInfo> ListObjWithQryString(string _objQry)
{
    List<ObjInfo> listToReturn = new List<ObjInfo>();
    char[] firstDelimiters = {'*'};
    string[] parsedValues = _objQry.Split(firstDelimiters,
       StringSplitOptions.RemoveEmptyEntries);
    foreach (string parsedValue in parsedValues)
    {
       if (parsedValue.Contains("OBJNAME"))
       {
           // WRITE CODE HERE
       }
    }
    return listToReturn;
}

现在我的问题是基于这样一个事实,即每个参数可能或可能不存在,所以查询字符串将会改变,我不想必须处理每81种可能性,特别是因为这可能并且最终将会改变。

是否有任何方法可以动态地建立一个查询到我的数据库取决于所获得的值,这样我可以只返回我正在寻找的值?

* EDIT *

这里有几个字符串的例子,我可能会结束:

*OBJNAME=[SWORD][OF][THOUSAND][TRUTHS]
// Seeking all objects named Sword of a Thousand Truths
*OBJNAME=[SWORD][OF][THOUSAND][TRUTHS*OBJNUMBER=[28]*COST=[9]+<*POWER=[3]+>=*RATING=[4]+<RARITY=[LEGENDARY]*ADDCOST=[6QGBA]*OBJCOLOR=[ALL]
// Seeking all objects named Sword of a Thousand Truths with number 28 with cost lesser than 9 with power greater or equal to 3 with rating lesser than 4 with rarity Legendary with additional cost 6QGBA with all colors
*OBJNAME=[SWORD][OF][THOUSAND][TRUTHS]*OBJTYPE=[ARTEFACT]*OBJNUMBER=[28]*COST=[9]+<*POWER=[3]+>=*RATING=[4]+<*OWNER=[STAN]*OBJSET=[WORLD OF WARCRAFT]
// Seeking all objects named Sword of a Thousand Truths with type Artefact with number 28 with cost lesser than 9 with power greater or equal to 3 with owner Stan with objSet World of Warcraft
*ADDCOST=[6QGBA]*OBJCOLOR=[ALL]
// Seeking all objects with additional cost 6QGBA with all colors
*ADDCOST=[6QGBA]*OBJCOLOR=[BLUE][RED][PURPLE]
// Seeking all objects with additional cost 6QGBA with specific color Blue, Red, Purple
*OBJTYPE=[ARTEFACT]*POWER=[3]+>=
// Seeking all objects with type Artefact and power greater or equal to 3

你会看到,我可能会给字符串加上不同的标签。如果需要,我可以粘贴其他信息。

* ALSO *

请记住,这就是我现在构建应用程序的方式,但如果有更好的方法,我愿意接受任何建议。

编辑2

多亏了@I4V,我有了一个实际分组值的字典。所以:

var dict = Regex.Matches(_cardQry, @"'*('w+)=([^'*$]+)").Cast<Match>()
                            .ToDictionary(x => x.Groups[1].Value,
                                          x => string.Join(" ", x.Groups[2].Value.Split(new char[] {'[', ']'})));

将给出一本字典。如果我用一个字符串在字典中执行foreach,其中第一个参数传递到那里,我最终得到这个:

键/值

OBJNAME= SWORD  OF  THOUSAND TRUTHS  
OBJTYPE= ARTIFACT 
OBJNUMBER= 28 
COST= 9 +>= //(small bug here, there should not be a "=" sign at the end, but it's not major)
POWER= 3 +<=
RATING= 4+<
OWNER= STAN
OBJSET= WORLD OF WARCRAFT
RARITY= LEGENDARY
ADDCOST= 4  W  G  U  G  R 
OBJCOLOR= ALL 

和这行代码:

var whereCondition = "WHERE " + String.Join(" AND ", dict.Select(kv => kv.Key + "='" + kv.Value + "'"));

我最终得到了一个非常有用的字符串,看起来像这样:

WHERE OBJNAME=' SWORD  OF  THOUSAND TRUTHS ' AND OBJTYPE=' ARTIFACT ' AND OBJNUMBER=' 28 ' AND COST=' 9 +<' AND POWER=' 3 +>' AND RATING=' 4 +<' AND OWNER=' STAN ' AND OBJSET='WORLD OF WARCRAFT ' AND RARITY=' LEGENDARY ' AND ADDCOST=' 4  W  G  U  G  R  ' AND OBJCOLOR=' ALL '

现在,问题不在于构建字符串,而在于如何使用它来进行查询调用。我是非常新的MVC应用程序,特别是数据库调用。我通常这样调用数据库:

var objQry = from o in m_DB.O
             where o.NAME == _nameProvided
             select o;

我如何使用字符串来进行这样的查询调用?

从具有不同值的字符串构建查询

您可以根据输入字符串创建字典。使用它会更简单。

string input = "*OBJNAME=[SWORD][OF][THOUSAND][TRUTHS]*OBJTYPE=[ARTEFACT]*OBJNUMBER=[28]*COST=[9]+<*POWER=[3]+>=*RATING=[4]+<*OWNER=[WRIGHT][STAN]*OBJSET=[RETURN TO RAVNICA]*RARITY=[LEGENDARY]*ADDCOST=[6QGBA]*OBJCOLOR=[ALL]";
var dict = input.Split(new char[]{'*'},StringSplitOptions.RemoveEmptyEntries)
             .Select(p => p.Split('='))
             .ToDictionary(kv => kv[0], 
                           kv => kv[1].Replace("[", "").Replace("]", " ").Trim());

或使用Regex

var dict2 = Regex.Matches(input, @"'*('w+)=([^'*$]+)").Cast<Match>()
            .ToDictionary(x => x.Groups[1].Value, 
                          x => String.Join(" ",x.Groups[2].Value.Split(new char[]{'[',']'},StringSplitOptions.RemoveEmptyEntries)));