持久的布尔逻辑

时间:2013-01-08 11:57:37

标签: c# sql sql-server ado.net boolean-logic

这是一种与设计相关的问题,而不是技术问题。 标题可能不完美随意编辑。

我有以下要求: 我想在Table Server的SQL Server 2012中保存特定jobEntity的资格(不要与SQL Server作业混淆)。 出于同样的目的,我有另一张表说资格,这可以节省对作业的资格,这与作业表具有参照完整性。 用于制作它的存储过程具有参数JobID和用户定义的模式表类型:

CREATE TYPE [dbo].[TableTypeQualificationJob] AS TABLE(
    [QualificationID] [int] NULL,
    [QualificationCriteria] [nvarchar](4000) NULL,
    [OptionTo] [bigint] NULL
)
GO

我在业务层有相应的实体。 因此,当用户创建多个作业资格时,他将List传递给函数,底层方法将列表转换为datatable,并使用存储过程添加到数据库中。

捕获是OR或AND中的资格。 例如,如果有5个资格说 qualification1 qualification2 qualification3 qualification4 qualification5

并以

强制执行作业
  

资格1或资格2或资格3和资格4   和资格5

所以它制作了三组

  

(资格1或资格2或资格3)AND   (资格4)和(资格5)

那么如何在QualificationEntity类和Database中解释它呢? 我使用ADO.NET通过手动将列表转换为DataTable来为用户定义的表类型调用SP,我该如何实现它?

1 个答案:

答案 0 :(得分:3)

我会将OrQualificationsAndQualifications存储为单独的实体,并将它们保存为Job实体的多对多引用,这样您就可以区分资格。< / p>

如果申请人具有合适的资格,您将检查AndQualification实体中的所有资格是否得到满足,以及OrQualifications实体中的任何资格是否得到满足。


编辑:

上述/初步答案旨在满足一份所需资格清单的要求,另一份要求至少需要一份资格清单。对我而言,这似乎已经足够好了,你确定你真的需要嵌套资格吗?相信我,使应用程序变得比它需要的更复杂是一个坏主意。

表达式树
嵌套资格是另一种野兽,这里有一个建议的解决方案:表达式存储为完整的二叉树(二叉树,其中每个节点恰好有0或2个子节点)。此树中的所有节点都包含运算符AND或OR(&amp;或|),但叶子除外,它们都是资格。

示例表达:
(A | B&amp; C)| (D&amp; E)

(从表达式到树的转换完全取决于您输入数据的方式,最简单的方法是手动创建树!)

作为一棵树:

      |
   /     \
  |       &
 / \     / \
A   &   D   E
   / \
  B   C

关于如何将此树持久保存到数据库,您有许多不同的选择,例如:

  • 一个层次模型,绝对最小值为两列,一个Id和一个ParentId。要获取树,您需要递归查询。对于关系数据库,此选项可能非常苛刻。
  • 将树序列化为例如xml(XmlSerializer)或json(json.NET)并将其另存为文本。

我个人会选择序列化选项,因为你总是需要完整的树,并且很容易反序列化为数据结构。

以下是一个示例数据结构:

public class Node
{
    public Node LeftChild { get; set; }
    public Node RightChild { get; set; }
}

class OperatorNode : Node
{
    public bool IsAnd { get; set; }
}

class QualificationNode : Node
{
    public bool IsQualificationMet { get; set; }
}

然后你需要一个可以解析这棵树并输出true或false的函数:

public bool EvaluateNode( Node node )
{
    var qualificationNode = node as QualificationNode;
    if ( qualificationNode != null )
    {
        return qualificationNode.IsQualificationMet;
    }
    var operatorNode = node as OperatorNode;
    if ( operatorNode.IsAnd )
    {
        return EvaluateNode( node.LeftChild ) && EvaluateNode( node.RightChild );
    }
    return EvaluateNode( node.LeftChild ) || EvaluateNode( node.RightChild );
}

免责声明:这就是所谓的快速和脏代码,请做些更好的事情。

其他选项
查看System.Linq.Expressions.Expression。它可用于以编程方式构建逻辑,因此这可能是您可以使用的。