XQuery/XPath应用

   最近参与的电子商务系统即将完成,不久前分析师提了一个需求:
   在系统上增加一个小的模块用来处理最终用户可以向我们提交在使用系统是遇到的一些问题。这样的我们的Support Team就可以更容易理解客户想说的到底是遇到了什么样的问题。
   针对这个需求,我们定义出了下面的实体:

Code


   数据库应用嘛,接下来考虑数据库的设计吧。这应该是很简单的,我这里也不唠叨了。然而,这样设计好吗?考虑到变化,后面我们可能还要增加一个小模块,用来处理最终用户对于系统的改进建议等等。这样的话,我们维护这些表会感觉有些不爽。我们可不可以这样设计,一个字段(TransactionNumber)存储编号,一个字段(WidgetCategory)存储分类,一个字段(WidgetContent)存储实际的内容(XML文本)。这样一来,我们就可以很灵活地给系统增加很多比较有用的Widgets.我们将WidgetEntity序列化为的XML文本存储在WidgetContent中,查询时,我们使用XQuery/XPath来查询WidgetContent,然后将过滤得到的WidgetContent反序列化为相应的WidgetEntity.

  针对这个需求,我们定义出了相应的查询条件实体:

Code


 

  那么我们如何构建相应的XPath表达式呢?
  我可不想一个手动构造。这里我写了一个自定义Attribute来帮助生成相应的XPath表达式:
  //XPathMappingAttribute

Code

  XPathMappingAttribute是一个可以应用在属性上的自定义Attribute,它有一个构造参数,就是要应用在这个属性上的XPath表达式的格式化字符串。这样,我们就可以利用反射技术根据属性相应的XPath表达式的格式化字符串以及属性的值来生成整个查询实体对应的XPath表达式。参考下面的代码:

  //XPathHelper

Code

      看下单元测试吧:

Code

    输出如下:

     XPathExpression:
/IssueReport/ErrorDescription[fn:contains(.,"description"] and /IssueReport[Status="状态:A"] and /IssueReport[SubmitDate>="2008-9-16 20:11:25"] and /IssueReport[SubmitDate<"2008-9-23 20:11:25"] and /IssueReport[ResolvedDate<"2008-9-23 20:11:25"] and 1=1

     细心的网友一定注意到后面加了一个" and 1=1"为什么要这样加呢?

     这是因为在使用WidgetContent.value("XPathExpression","bit")=1时,其中的当XPathExpression只有一个,比如/IssueReport/ErrorDescription[fn:contains(.,"description"] 时,就会报下面的一个异常:

     Msg 2389, Level 16, State 1, Line 5
XQuery [dbo.ApplicationWidgets.WidgetContent.value()]: 'value()' requires a singleton (or empty sequence), found operand of type 'xdt:untypedAtomic *'

     这是因为value(parm1,parm2)的param1在param2是bit类型时必须是一个逻辑表达式,在这里我们就要为当只有一个查询条件是构造一个加上" and 1=1"的一个逻辑表达式.

     并且注意XPathExpression中的and必须为小写,不然会遇到下面的异常:

     Msg 2370, Level 16, State 1, Line 6
XQuery [dbo.ApplicationWidgets.WidgetContent.value()]: No more tokens expected at the end of the XQuery expression. Found 'AND'.

     诚找合作伙伴或有好的投资项目的老板.呵呵

原文地址:https://www.cnblogs.com/fuhongwei041/p/1297420.html