首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将规则应用于数据

将规则应用于数据
EN

Stack Overflow用户
提问于 2011-08-09 01:15:09
回答 2查看 744关注 0票数 0

在我的(C# + SQL Server)应用程序中,用户将能够定义数据规则,例如:

代码语言:javascript
复制
ITEM_ID = 1 
OR (ITEM_NAME LIKE 'something' AND ITEM_PRICE > 123 
AND (ITEM_WEIGHT = 456 OR ITEM_HEIGHT < 789))

要验证的项目集总是不同的,但它们不是一个很大的数字。但是,规则的数量很多(假设是100000)。

我如何检查哪些规则验证了(还考虑到性能)给定的一组数字?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-08-09 04:50:57

您可以使用一些Microsoft自己的T-SQL解析引擎。

您可以在程序集Microsoft.Data.Schema.ScriptDom.dllMicrosoft.Data.Schema.ScriptDom.Sql.dll中找到它们。

代码语言:javascript
复制
TSql100Parser parser = new TSql100Parser(false);

IList<ParseError> errors;
Expression expr = parser.ParseBooleanExpression(
        new StringReader(condition),
        out errors
    );

if (errors != null && errors.Count > 0)
{
    // Error handling
    return;
}

如果没有得到任何错误,则该字符串是一个有效的过滤器表达式。尽管可能会有一些有害的表达。

如果您愿意,您可以通过您自己的访问器运行表达式来检测任何不需要的构造(例如子查询)。但请注意,对于Visit(...)ExplicitVisit(...),您必须覆盖几乎所有的650重载。分部类在这里是很好的。

当您感到满意时,然后可以构建一个完整的SELECT语句,其中包含所有表达式:

代码语言:javascript
复制
var schemaObject = new SchemaObjectName();
schemaObject.Identifiers.Add(new Identifier {Value = "MyTable"});

var queryExpression = new QuerySpecification();
queryExpression.FromClauses.Add(
    new SchemaObjectTableSource {SchemaObject = schemaObject});

// Add the expression from before (repeat as necessary) 
Literal zeroLiteral = new Literal
{
    LiteralType = LiteralType.Integer,
    Value = "0",
};
Literal oneLiteral = new Literal
{
    LiteralType = LiteralType.Integer,
    Value = "1",
};
WhenClause whenClause = new WhenClause
{
    WhenExpression = expr, // <-- here
    ThenExpression = oneLiteral,
};
CaseExpression caseExpression = new CaseExpression
{
    ElseExpression = zeroLiteral,
};
caseExpression.WhenClauses.Add(whenClause);
queryExpression.SelectElements.Add(caseExpression);

var selectStatement = new SelectStatement {QueryExpression = queryExpression};

..。并将其转换回一个字符串:

代码语言:javascript
复制
var generator = new Sql100ScriptGenerator();
string query;
generator.GenerateScript(selectStatement, out query);

Console.WriteLine(query);

输出:

代码语言:javascript
复制
SELECT CASE WHEN ITEM_ID = 1
                 OR (ITEM_NAME LIKE 'something'
                     AND ITEM_PRICE > 123
                     AND (ITEM_WEIGHT = 456
                          OR ITEM_HEIGHT < 789)) THEN 1 ELSE 0 END
FROM   MyTable

如果这个表达式太大而无法处理,您总是可以将规则拆分成块,以便同时运行几个块。

但是,要被允许重新分发Microsoft.Data.Schema.ScriptDom.*.dll文件,您必须拥有Visual Studio Team System的许可证(这至少包含在VS /旗舰版中吗?)

链接:http://blogs.msdn.com/b/gertd/archive/2008/08/22/redist.aspx

票数 1
EN

Stack Overflow用户

发布于 2011-08-09 02:53:48

这看起来您的“规则”或条件应该改为在C#中执行。

如果您真的要在SQL语句的WHERE子句中输入100,000个OR和and,那么您将很难扩展您的应用程序。我可以想象,您必须将任意100,000个条件的任意集合应用于数据集,并且每个排列都能很好地执行,这会造成多大的索引混乱。

相反,我会运行一个基本的select查询,读取每一行,然后在C#中对其进行过滤。然后,您可以通过单独应用每个规则并跟踪通过/失败,来跟踪每行通过和不通过的条件/规则。

当然,如果您正在查询一个非常大的表,那么性能可能会成为一个问题,但是您说“要验证的项目集……不是一个很大的数字”,所以我假设取回表的所有数据并在代码中执行您的规则,或者预先应用一些基本的过滤,然后在代码中进行更具体的过滤会相对较快。

出于好奇,用户是如何输入这些“规则”的,比如:

代码语言:javascript
复制
ITEM_ID = 1
OR (ITEM_NAME LIKE 'something' AND ITEM_PRICE > 123
AND (ITEM_WEIGHT = 456 OR ITEM_HEIGHT < 789))

请告诉我,它们不是在输入实际的SQL查询(以文本形式),您只是将它们添加在一起,例如:

代码语言:javascript
复制
var sql = "select * from myTable where ";
foreach(var rule in rules)
    sql += rule;

也许是某种规则构建器UI来构建这些类似SQL的语句?

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6985892

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档