XML 高级应用

转载:向 XPath 中添加自定义函数

Web 应用程序中处理数据库更新的两种方法

Microsoft Corporation

Prajakta Joshi

2002 年 10 月 8 日

摘要:特邀作家 Prajakta Joshi 讨论了如何使用 .NET 框架 SDK 中的 System.Xml API 为 XPath 创建自定义函数。主题涉及向 XPath 1.0 中添加扩展函数、展望 XPath 2.0 以及使用 XSLT 中的扩展函数。(14 页打印页)

*

XMLXSL公共新闻组中,对扩展函数 的请求是一个经常讨论的主题。撰写本文的动机是因为我注意到有大量的用户帖子涉及该主题。 XPath 1.0中的 XPath 表达式能够返回以下四个基本 XPath 数据类型之一:

字符串

数值

布尔值

节点集

XSLT 变量向表达式语言中引入了一个附加类型 — result tree fragment(结果树片段)。

XPath 中的核心函数库其他几个 XSLT 特定的附加函数提供了几个用来操作 XPath 数据类型的基本工具。纵观这些函数,您会发现这不是一个能够满足所有用户需要的完善集合。

XPath 类型 函数

节点集

last()、position()、count()、id()、local-name()、namespace-uri()、name()

字符串

string()、concat()、starts-with()、contains()、substring-before()、substring-after()、substring()、string-length()、normalize-space()、translate()

布尔值

boolean()、not()、true()、false()、lang()

数值

number()、sum()、floor()、ceiling()、round()

XSLT 1.0 中的新增函数

document()、key()、format-number()、current()、unparsed-entity-uri()、generate-id()、system-property()

需要操作非 XPath 数据类型(例如,日期)或者用 XPath 数据类型执行功能强大的/自定义数据操作的 XML 开发人员通常需要额外的函数。本文旨在概述如何使用 Microsoft .NET 框架 SDK 中的 System.XmlAPI 来为 XPath 实现自定义函数。

两个字符串的比较

在编写我的第一个 XPath 查询时,我需要对两个字符串执行不区分大小写的比较。我编写的 books.xml 如下所示:

<bookstore xmlns:my="urn:http//mycompany.com/">

   <book style="young adult">

      <title>Harry Potter and the Goblet of Fire</title>

      <author>

         <first-name>Mary</first-name>

         <last-name>Gradpre</last-name>

      </author>

      <my:price>8.99</my:price>

   </book>

   <book style="young fiction">

      <title>Lord of the Rings</title>

      <author>

         <first-name>J.</first-name>

         <last-name>Tolkien</last-name>

      </author>

      <my:price>22.50</my:price>

   </book>

</bookstore>

我寻找到一个类似于 XPath 1.0 字符串函数 中的 String.Compare()的函数。可用在我的解决方案中的最接近的函数是 translate()。我通过以下代码片段使用 System.Xml.XPath命名空间中的 XPath 类解决了该问题:

using System;

using System.Xml;

using System.Xml.XPath;

public class sample

{

   public static void Main(string []args)

   {

      // Load source XML into XPathDocument.

      XPathDocument xd = new XPathDocument(args[0], XmlSpace.Preserve);

      // Create XPathNavigator from XPathDocument.

      XPathNavigator nav = xd.CreateNavigator();

      XPathExpression expr;

      expr = 

nav.Compile("/bookstore/book/title[translate(.,'abcdefghijklmnopqrstuvwxyz',

'ABCDEFGHIJKLMNOPQRSTUVWXYZ') = 'HARRY POTTER AND THE GOBLET OF FIRE']");

      XPathNodeIterator iterator = nav.Select(expr);

      // Iterate through selected nodes.

      while (iterator.MoveNext())

      {

         Console.WriteLine("Book title: {0}", iterator.Current.Value);

      }

   }

}

此代码生成如下输出结果:

Book title: Harry Potter and the Goblet of Fire

尽管此解决方案有点长,但我还是解决了我的问题。在几天之后编写 XPath 查询时,我要在由正则表达式匹配定义的位置将字符串拆分成子字符串的数组。

<?xml version="1.0" encoding="utf-8" ?> 

<Books>

   <Book>

      <Title>Stephen Hawking's Universe: The Cosmos Explained</Title>

      <Authors>David Filkin, Stephen Hawking</Authors>

   </Book>

   <Book>

      <Title>Writing Secure code</Title>

      <Authors>Michael Howard, David LeBlanc</Authors>

   </Book>

</Books>

我要从 <Authors> 元素的逗号分隔列表中找出第 n 个作者的姓名 — 一个有点复杂的字符串操作问题。我认为这是一个学习如何实现 XPath 自定义扩展函数的好机会。

实现 XPath 中的扩展函数

我发现 XPath 1.0 建议没有为扩展函数定义机制。但好消息是,我可以为 XPath 处理器提供一个自定义执行上下文,以便解析 XPath 表达式中用户定义的函数和变量。

下图解释了我的解决方案内 System.Xml.Xsl 命名空间中 XsltContext 类、IXsltContextFunction 接口和 IXsltContextVariable接口的角色。

XsltContext 的角色

1. XsltContext 的角色

解决方案中的关键步骤

1.XPathExpression.SetContext(CustomContext) 提供一个 XPath 处理器 (XPathNavigator),它具有用来解析用户定义的函数和变量的自定义上下文。CustomContext(从抽象类 XsltContext 派生)实现两个关键方法:ResolveFunction()ResolveVariable()

2.当 XPathNavigator 在 XPathExpression 中遇到用户定义的函数时,它会针对自定义上下文调用 ResolveFunction() 方法。ResolveFunction() 返回从 IXsltContextFunction 派生的适当自定义函数。

3.XPathNavigator 在运行时使用所提供的参数针对这个自定义函数调用 Invoke() 方法。

4.当 XPathNavigatorXPathExpression 中检测到用户定义的变量时,它会针对自定义上下文调用 ResolveVariable() 方法。ResolveVariable() 返回从 IXsltContextVariable 派生的适当的自定义变量。

5.XPathNavigator 在运行时针对这个自定义变量调用 Evaluate() 方法。

我决定编写一个自定义的 XPath 函数 — Split(),使该函数的行为类似于 .NET SDK 中的 RegEx.Split()方法。下面介绍如何将所有这些代码片段合并在一起。

XsltContext 类的角色

首先,我实现了我的自定义 XsltContext,以便给 XPath 处理器提供有关解析用户定义的函数所需的信息。ResolveFunctionResolveVariableXsltContext 类的两个关键方法,用户必须重写它们才能实现自定义解析。这些方法在运行时由 XPathNavigator调用,以便解析对 XPath 查询表达式中用户定义的函数和变量的引用。

请注意,我在 CustomContext 类中封装了一个 ResolveVariable对象。此对象是 XPath 表达式中的变量的容器。

public class CustomContext : XsltContext

{

   // XsltArgumentList to store my user defined variables

   private XsltArgumentList m_ArgList;

   // Constructors 

   public CustomContext()

   {}

   public CustomContext(NameTable nt) : base(nt)

   {

   }

   public CustomContext(NameTable nt, XsltArgumentList argList) : base(nt)

   {

      m_ArgList = argList;

   }

   // Returns the XsltArgumentList that contains custom variable definitions.

   public XsltArgumentList ArgList

   {

      get

      { 

         return m_ArgList;

      }

   }

   // Function to resolve references to my custom functions.

   public override IXsltContextFunction ResolveFunction(string prefix, 

string name, XPathResultType[] ArgTypes)

   {

      XPathRegExExtensionFunction func = null;

      // Create an instance of appropriate extension function class.

      switch (name)

      {

         case "Split":

            // Usage 

            // myFunctions:Split(string source, string Regex_pattern, int n) returns string

            func = new XPathRegExExtensionFunction("Split", 3, 3, new 

XPathResultType[] {XPathResultType.String, XPathResultType.String, 

XPathResultType.Number}, XPathResultType.String);

            break;

         case "Replace":

            // Usage

            // myFunctions:Replace(string source, string Regex_pattern, 

string replacement_string) returns string

            func = new XPathRegExExtensionFunction("Replace", 3, 3, new 

XPathResultType[] {XPathResultType.String, XPathResultType.String, 

XPathResultType.String}, XPathResultType.String);

            break;

      }

      return func;

   }

   // Function to resolve references to my custom variables.

   public override IXsltContextVariable ResolveVariable(string prefix, string name)

   {

      // Create an instance of an XPathExtensionVariable.

      XPathExtensionVariable Var;

      var = new XPathExtensionVariable(name);

      return Var;

   }

   public override int CompareDocument(string baseUri, string nextbaseUri)

   {

      return 0;

   }

   public override bool PreserveWhitespace(XPathNavigator node)

   {

      return true;

   }

   public override bool Whitespace

   {

      get

      {

         return true;

      }

   }

}

IXsltContextFunction 接口的角色

下一步是实现供 CustomContext 类使用的

IXsltContextFunction

接口。此对象的

Invoke()

方法在运行时由 XPathNavigator利用所提供的参数进行调用。

public class XPathRegExExtensionFunction : IXsltContextFunction

{

   private XPathResultType[] m_ArgTypes;

   private XPathResultType m_ReturnType;

   private string m_FunctionName;

   private int m_MinArgs;

   private int m_MaxArgs;

   // Methods to access the private fields.

   public int Minargs

   {

      get

      {

         return m_MinArgs;

      }

   }

   public int Maxargs

   {

      get

      {

         return m_MaxArgs;

      }

   }

   public XPathResultType[] ArgTypes

   {

      get

      {

         return m_ArgTypes;

      }

   }

   public XPathResultType ReturnType

   {

      get

      {

         return m_ReturnType;

      }

   }

   // Constructor

   public XPathRegExExtensionFunction(string name, int minArgs, int 

maxArgs, XPathResultType[] argTypes, XPathResultType returnType)

   {

      m_FunctionName = name;

      m_MinArgs = minArgs;

      m_MaxArgs = maxArgs;

      m_ArgTypes = argTypes;

      m_ReturnType = returnType;

   }

   // This method is invoked at run time to execute the user defined function.

   public object Invoke(XsltContext xsltContext, object[] args, 

XPathNavigator docContext)

   {

      Regex r;

      string str = null;

      // The two custom XPath extension functions

      switch (m_FunctionName)

      {

         case "Split":

                r = new Regex(args[1].ToString());

            string [] s1 = r.Split(args[0].ToString());

            int n = Convert.ToInt32(args[2]);

            if (s1.Length < n)

               str = "";

            else

               str = s1[n - 1];

            break;

         case "Replace":

            r = new Regex(args[1].ToString());

            string s2 = r.Replace(args[0].ToString(), args[2].ToString());

            str = s2;

            break;

      }

      return (object) str;

   } 

}

IXsltContextVariable 接口的角色

XPath 表达式中可以包含用户定义的变量引用,例如:

XPathExpression expr1 = nav.Compile("myFunctions:Split(string(.), ',', 

$var

)");

我需要实现 IXsltContextVariable接口并重写 Evaluate()方法(此方法在运行时

public class XPathExtensionVariable : IXsltContextVariable

{

   // The name of the user-defined variable to resolve

   private string m_VarName;

   public XPathExtensionVariable(string VarName)

   {

      m_VarName = VarName;

   }

   // This method is invoked at run time to find the value of the user defined variable.

   public object Evaluate(XsltContext xsltContext)

   {

      XsltArgumentList vars = ((CustomContext) xsltContext).ArgList;

      return vars.GetParam(m_VarName, null);

   }

   public bool IsLocal

   {

      get

      {

         return false;

      }

   }

   public bool IsParam

   {

      get

      {

         return false;

      }

   }

   public XPathResultType VariableType

   {

      get

      {

         return XPathResultType.Any;

      }

   }

}

把代码合并在一起

最后,我使用了 XPathExpression.SetContext()方法,将它传入我的自定义上下文对象。图 1 汇总了该解决方案中的所有步骤。请注意,XsltContext 类是从 XmlNamespaceManager中继承而来的,而且通过使用 AddNamespace()向集合中添加了我的自定义命名空间。

using System;

using System.Xml;

using System.Xml.Xsl;

using System.Xml.XPath;

using System.Text.RegularExpressions;

public class sample

{

   public static void Main(string []argc)

   {

      // Load source XML into XPathDocument.

      XPathDocument doc = new XPathDocument("books.xml", XmlSpace.Preserve);

      // Create XPathNavigator from XPathDocument.

      XPathNavigator nav = doc.CreateNavigator();

      // Add user-defined variable to the XsltArgumentList.

      XsltArgumentList varList = new XsltArgumentList();

      varList.AddParam("var", "", 2);

      // Compile the XPathExpression.

      // Note that the compilation step only checks the query expression

      // for correct XPath syntax.

      // User defined functions and variables are not resolved.

      XPathExpression expr1 = nav.Compile("myFunctions:Split(string(.), ',', $var)");

      // Create an instance of a custom XsltContext object.

      CustomContext cntxt = new CustomContext(new NameTable(), varList);

      // Add a namespace definition for myFunctions prefix.

      cntxt.AddNamespace("myFunctions", "http://myXPathExtensionFunctions");

      // Associate the custom context with the XPathExpression object.

      expr1.SetContext(cntxt);

      XPathNodeIterator it = nav.Select("/Books/Book/Authors");

      while (it.MoveNext())

      {

         Console.WriteLine("Authors: {0}", it.Current.Value);

         Console.WriteLine("Second author: {0}", it.Current.Evaluate(expr1));

        }

   }

}

运行此代码会生成如下输出结果:

Authors: David Filkin, Stephen Hawking

Second author:  Stephen Hawking

Authors: Michael Howard, David LeBlanc

Second author:  David LeBlanc

扩展函数的其他用法

在我发现了使用扩展函数的机制之后,在用 XPath编程时,我在其他许多数据操作的情况下都使用了扩展函数。一些其他情况包括:

操作日期:对两个日期字符串进行比较是常见的操作。为了实现此目的,我使用了 System.DateTime.Compare()方法。

操作数值:Math方法。 类为常见的数学运算提供一组详尽的方法。我将 Abs() 方法用作自定义函数。

操作日期:对两个日期字符串进行比较是常见的操作。为了实现此目的,我使用了 System.DateTime.Compare()方法。

操作字符串:String类为常见的字符串操作提供一组详尽的方法。我发现 ToUpper()ToLower() 方法在被用作为自定义函数时非常有用。

这种情况数不胜数。根据您的具体情况,可以在您的自定义函数中使用任何 .NET 类。

未来的方向:XPath 2.0

由于 W3C XML 架构数据类型日益与 XPath 2.0集成,因此,Xquery 1.0 和 XPath 2.0 函数和运算符将为 XML 开发人员提供一个比当前存在于 XPath 1.0 中的函数更为丰富的函数库。这不会完全消除 XPath 2.0 对用户定义的函数的需要。对于 XML 的功能强大、可扩展的查询语言来说,扩展的机制将是不可或缺的。

XSLT 中的扩展函数

XSLT 1.0XslTransform实现将命名空间 urn:schemas-microsoft-com:xslt 用作扩展命名空间。它具有对 <msxsl:node-set>扩展函数和 <msxsl:script>扩展元素的内置支持。

在 XSLT 中,可通过两种方法来实现用户定义的函数:

1.样式表脚本

2.向 XsltArgumentList中添加扩展对象

posted @ 2004-11-08 20:48 sharpen 阅读(1) | 评论 (0)编辑 收藏

2004年11月05日 #

智能客户端高级开发

http://www.microsoft.com/china/msdn/events/featureevents/2004/SmartClientSeminar/index.aspx

我的关于smart client开发的网络讲座


经过设计,智能客户端应用程序可以将胖客户端应用程序的优点与瘦客户端应用程序的部署和可管理性优点结合起来,然而,要完全实现智能客户端应用程序的优点,需要考虑许多体系结构和设计问题。 智能客户端高级开发系列讲座提供了设计和实现智能客户端应用程序的最佳实践,从而使您能够在尽可能短的时间内实现智能客户端应用程序的优点。 XML 高级应用
XML 高级应用
XML 高级应用 第一天
XML 高级应用 Smart Client 介绍
        智能客户端应用程序是瘦客户端应用程序的强大替代产品。它们可以为用户提供内容丰富且响应迅速的用户界面,提供脱机工作的能力,并且提供利用本地硬件和软件资源的方法。智能客户端为用户提供了在强大且直观的客户端环境中访问信息和远程服务的能力,并且是一种用来开发灵活的、面向用户的应用程序以及提高用户工作效率和满意度的有效的解决方案。
        本讲座首先对四天的课程进行了简要的介绍,然后介绍了智能客户端的定义、特点,与其他应用程序的比较以及智能客户端的商业价值等内容,并演示了典型的Smart Client应用程序---TaskVision。
XML 高级应用
XML 高级应用 使用Windows窗体技术构建Smart Client用户界面
        Smart Client 应用程序能够提供了内容丰富且响应迅速的用户界面,通过VS.NET2003的集成开发环境,您可以快速方便的设计功能强大的Smart Client客户端窗体界面, 本讲座主要介绍VS.NET2003的新控件和新特性,包括ContextMenu, ToolTip, Splitter, NotifyIcon在内的一系列新控件的使用方法和诸如Anchoring,Docking等一些新的特性。并讨论了如何在VS.NET中集成原有的ActiveX控件,如何进行可视化的继承和怎样开发多文档界面的应用程序。
XML 高级应用
XML 高级应用 在Smart Client程序中使用.NET Framework实现增强的功能
        .NET 框架可以帮助您实现智能客户端应用程序的许多特征。该框架提供了具备自我描述能力且牢固绑定的程序集,并且支持单独和并列安装应用程序的多个版本,从而有助于减少与胖客户端相关联的应用程序部署和脆弱性问题。.NET 框架基类库为与 Web 服务进行交互提供了广泛的支持,并且提供了 Windows 窗体。通过使用公共语言运行库 (CLR),您可以利用任何受到 .NET 支持的语言来开发智能客户端。
        本讲座首先介绍了.NET Framework和公共语言运行库的功能、特点以及运行机制,其次结合实例对.NET Framework基类库中常用的几个类,如文件IO、XML、GDI+等进行了介绍。
XML 高级应用
XML 高级应用 在Smart Client程序中实现数据访问
        在智能客户端应用程序中,可在客户端上使用应用程序数据。要使您的智能客户端有效工作,很重要的一点是对该数据进行适当的管理,以确保其有效、一致和安全。
        本讲座主要介绍了与数据访问有关的内容。首先详细对比了ADO与ADO.NET的区别,然后介绍了如何使用ADO.NET在联机环境和客户端执行操作,接着对强类型的数据集、存储过程、图形化的数据工具及创建离线的应用程序等内容进行了介绍。
XML 高级应用
XML 高级应用 第二天
XML 高级应用 构建和使用 Web Service
        Web Service 使用基于SOAP的XML消息来传递信息。因此,Web Service非常适合于横跨网络和企业防火墙的应用程序,如需要通过 Internet 与服务通讯的智能客户端。
        本讲座深入浅出的介绍了Web Service概述和体系结构,如何开发和使用Web Service,以及如何使用Web Service作为数据访问层组件的数据提供者返回复杂的数据类型。最后介绍了Web Service高级开发技术,Web Service Enhancement相关的内容,包括如何对SOAP消息进行加密、签名等。
XML 高级应用
XML 高级应用 开发智能设备应用程序
        智能设备包括Pocket PC、SmartPhone 以及其他超小型台式设备(如机顶盒)。智能设备应用程序是在这些智能设备上运行的应用程序。这些应用程序是使用.NET框架压缩版开发的。. NET框架压缩版具有完整.NET框架的许多功能,支持XML,并且消耗Web 服务。它被进行了优化以便在超小型台式设备上使用,并且它包含用于开发用户界面的 Windows 窗体设计器。通过使用 Visual Studio .NET 智能设备项目,您可以开发能够在 .NET 框架压缩版上运行的移动智能客户端。
        本讲座在介绍了Compact Framework的基础上,着重的介绍了如何构建智能设备应用程序,包括用户界面开发、数据访问、应用Web Service、非托管代码的调用等一系列的内容。
XML 高级应用
XML 高级应用 Smart Client应用程序的部署
        智能客户端应用程序在客户端计算机上执行本地处理,因此需要将它们部署到这些计算机上。过去,在客户端计算机上长期部署、更新、维护和卸载应用程序非常困难而且存在很多问题,如COM组件、DLL地狱等等,.NET的出现最大限度的降低了应用程序部署和升级的困难。 您可以通过Xcopy、MSI、No-touch 部署等方法来简单轻松的部署Smart Client,并且使用Updater Application Block来设计自动更新的解决方案。
        本讲座着重介绍了三种Smart Client应用程序的部署方法,分别是Xcopy、Windows Installer 部署以及No-touch 部署,并用Demo演示了如何使用这三种部署方法来部署Smart Client应用程序。
XML 高级应用
XML 高级应用 Smart Client 的安全性
        智能客户端将逻辑和数据分布到客户端计算机;因此需要考虑的安全性和与瘦客户端应用程序相关的安全性是不同的。在保护智能客户端时,可以从身份验证、授权、数据验证、保护敏感数据、代码访问安全等各方面来考虑Smart Client的安全性。
        本讲座围绕着Smart Client 的安全性进行了深入的探讨,对如何保护数据库安全、保护代码安全、加密离线数据、控制本地资源的访问、控制Web Service的访问、保护业务逻辑等一系列的问题提出了解决方案。
XML 高级应用
XML 高级应用 第三天
XML 高级应用 使用Visual Studio Tools for Office开发Office应用
      Visual Studio Tools for Office工具套件使开发人员能够通过使用 Microsoft Visual Studio .NET 2003 开发系统来创建托管代码 Office 智能客户端应用程序。开发人员可以将文档解决方案与基础代码分开。通过将托管代码与 Microsoft Office 一起使用,开发人员可以获得更多为智能客户端解决方案创建、部署和管理更新的有效选项。
      本讲座首先对Visual Studio Tools for Office做了一个概览,其次介绍了如何使用VS.NET开发托管代码的Office应用程序,最后对一些比较高级的内容如安全和部署问题进行了探讨。
XML 高级应用
XML 高级应用 在 Word 2003 和 Excel 2003 中使用 XML和 XML Web Service
      Microsoft Office System 2003 为您提供了用来生成智能客户端应用程序的有用平台。通过 Office 智能客户端解决方案,您可以将通过 Web 服务访问的数据源与 Word 2003、Excel 2003、InfoPath 2003 或其他 Office应用程序的功能集成起来,以开发智能客户端解决方案。这样的 Office 智能客户端应用程序可以将 Web Service公开的数据转换为有用信息的工作流和任务指导、数据分析、协作、报告和呈现功能。
      本讲座主要介绍了Office与XML 的集成、Office调用Web Service、Office对象等一系列相关的概念、原理、实现,并演示了如何在Word 2003和Excel 2003中使用XML和XML Web Service。
XML 高级应用
XML 高级应用 应用 InfoPath 实现企业 Office 解决方案
      InfoPath 2003 是能够使用类似于表单的界面从用户那里收集结构性数据的应用程序。InfoPath 2003 提供了对 XML Web 服务(一种基于表单的用户界面)的支持,以及对标准技术(如 WSDL 和 UDDI)的支持。InfoPath 2003 支持有限的脱机使用,方法是允许用户在脱机时与表单进行交互,然后允许用户在联机时将该表单转发给 Web 服务。
      本讲座对Office 2003新增的InfoPath 应用程序的应用和特性进行了详细的介绍,并结合实例讲述了如何设计InfoPath 表单模板、填写InfoPath表单、使用 InfoPath 获取和提交数据等方向的内容。
XML 高级应用
XML 高级应用 构建Smart Document 和 Research Library 服务
      Smart Document(智能文档)为用户提供了更为强大的与文档和业务Web Service 进行交互的方法。它使得您能够在Office 2003 中创建自己的任务窗格,可以使用该任务窗格向用户显示上下文信息、任务、工具、后续步骤以及其他相关信息。用户能够通过与该任务窗格交互来启动其他操作和任务,从而可以构建综合性业务解决方案。Research Library 服务是Office 2003新增的功能,它能够帮助简化从Web、企业数据库和参考文献中查找和选择信息,然后输入到文件中的这一工作流程。
      本讲座全面的介绍了Smart Document和 Research Library概念、工作原理和构建方法。
XML 高级应用
XML 高级应用 第四天
XML 高级应用 设计偶尔连接的Smart Client 应用程序
      智能客户端的特性之一是支持偶尔连接的用户,从而使用户可以在明确脱机、使用低带宽或高延迟网络,或者连接时断时续的情况下继续高效地工作。
      本讲座主要讨论了您在设计和生成偶尔连接到网络的智能客户端应用程序时可能面临到的问题。介绍了连接性的概念,两种实现脱机功能的主要方法,并且讨论了您在使应用程序可供脱机使用时需要考虑的一些问题。
XML 高级应用
XML 高级应用 Smart Client 应用——Issuevision 案例分析
      IssueVision是典型的Smart Client 应用程序,它具有利用本地资源、利用网络资源、支持偶尔连接的用户、提供智能安装和更新等特点,它为我们学习Smart Client技术提供了优秀的案例。请随着我们课程来一步一步的分析该应用程序是如何设计与构建的,并讨论了IssueVision的数据安全和更新维护等方面的内容。

posted @ 2004-11-05 22:54 sharpen 阅读(294) | 评论 (0)编辑 收藏

2004年11月04日 #

Smart Client开发: 使用AppUpdater组件

本来今天打算介绍Updater Application Block的,后来想想一些朋友经常反馈说用将UAB集成到自己开发的应用程序中太麻烦了,询问有没有更简单的方法布署智能客户端。在Whidbey的ClickOnce出来之前,答案当然还是有的,那就是使用AppUpdater组件。在美国举行的TechED 2004上介绍的IssueVision,TaskVision这些经典的Smart Client Demo用的都是这个组件来实现智能客户端的布署。

使用AppUpdater组件要用到下面这些文件:大家可以在http://windowsforms.net/downloads/GDN/dotnetupdater.zip 中下载
文件名               功能描述
AppStart.exe      类似中介代理的程序,由它来启动真正的应用程序。不直接启动主应用程序是为了防止主应用程序升级的过程中被锁死而造成升级失败。
AppStart.config      AppStart.exe的配置文件,它指定要启动的应用程序所在目录,以及要启动应用程序的名称
appupdater.dll      最重要的部件,自动升级的主要组件
system.Resources.dll      资源文件
mscorlib.Resources.dll      核心资源文件
UpdateVersion.xml      服务器端版本升级配置文件

OK,开始介绍如何使用它吧。

(1) .在Custom Control中导入AppUpdater
(2).配置自动下载选项

AutoFileLoad      :True
ChangeDetectionMode      ServerManifestCheck
UpdateUrl      http://YourServerDomainName/SmartServer/UpdateVersion.xml
ShowDefaultUI: True

AutoFileLoad 可以让 服务器上的文件动态加载,大家可以把它想像成 Un-Touch 部署中的Assembly.LoadFrom类似的功能
ChangeDetectonMode是设置检测模式:根据配置文件进行检测,也就是UpdateUrl属性指定的文件。如果设成DirectFileCheck则是比较每一个文件的时间戳来决定要不要下载这个文件。
UpdaterUrl指服务器上的更新配置文件,其中UpdateVersion.xml内容如下:
<VersionConfig>
      <AvailableVersion>2.0.0.0</AvailableVersion>
      <ApplicationUrl>http://YourServerDomainName/SmartServer/Ver/</ApplicationUrl>
</VersionConfig>

UpdateVersion.xml解释:
<AvailableVersion>2.0.0.0</AvailableVersion>
告诉客户端目前可用的版本,客户端appupdater组件会比较本地主应用程序版本号和该项配置的版本号,如果比本地的版本号更高,则进行下载更新。

<ApplicationUrl>http://YourServerDomainName/SmartServer/Ver/</ApplicationUrl>
告诉客户端到哪个网址进行下载更新

建议大家把这个属性设置成Dynamic,即从配置文件中读出来,不过,要让服务器的.config文件允许被下载,我们还要在IIS中 ASP.net应用程序”配置“中对它进行设置,默认是不允许访问的。

ShowDefaultUI表示下载结束时用一个简单的界面提示你要不要启动新版本。你还可以用自己的窗体显示,方法是设成False,并在OnUpdateComplete事件中写代码把你的窗体显示出来。

当然,还有一些其他的属性,比如,是否要使用公钥(可以是一个,也可以提供一个Assembly,里面包括多个公钥)验证要下载的文件。由于时间关系,我就不多说了。

(3) 使用AppStart.exe启动实际的应用程序。
(4) 在IIS把下载文件夹设成允许目录浏览,因为AppUpdater要枚举里面的所有文件,并把它们都下载到本地。如果是Windwos 2003,麻烦一点,要允许WebDAV,并把.config文件设置成允许下载。
(5) 做个msi安装文件,打包应用程序,这样,当应用程序运行时,它就能自动判断有无最新版本,并下载到本地运行。

posted @ 2004-11-04 16:36 sharpen 阅读(227) | 评论 (4)编辑 收藏

.net开发从入门到精通Webcast

可以直接访问:http://www.microsoft.com/china/msdn/events/featureevents/2004/MSDevTrainingCourse.mspx 
大家如果对Webcast的内容有什么问题,可以直接和我联系,我会尽快解答。
希望大家多多支持中文MSDN站点。
下次我可能会把VS.net团队开发的内容放上去。

1、Windows窗体应用程序开发 
 2、Delegates and Events 
 3、XML与SOAP 
 4、.NET数据库高级应用:数据缓存;连接池管理;分布式事务 
 5、WEB Service高级应用 
 6、NET中的I/O管理:Data Streams and Fils 
 7、ADO.NET访问Oracle数据库 
 8、.NET 组件开发 
 9、.NET序列化 
 10、与非托管代码交互操作 
 11、.NET Remoting 

1、Windows窗体应用程序开发
VS.NET IDE是一个高度可视化,集成和高效的开发环境。她能提供设计、开发、调试和部署Windows应用程序和Web应用程序所需的各种工具。比起VS6.0,她又提供了许多功能强大的组件并采用了很多新的特性,使得开发人员能够轻松简单高效的创建Windows窗体应用程序。

本讲座主要介绍VS.NET2003的新控件和新特性,包括ContextMenu, ToolTip, Splitter, NotifyIcon在内的一系列新控件的使用方法和诸如Anchoring,Docking等一些新的特性。并讨论了如何在VS.NET中集成原有的ActiveX控件,如何进行可视化的继承和怎样开发多文档界面的应用程序。

下载

返回页首
2、Delegates and Events
Microsoft .NET框架使用一种称为Delegate代理的技术来提供回调函数机制,从而极大地增加了应用程序的灵活性。同时,代理还集成了按序调用多个方法的能力,并且同时支持调用静态方法和实例方法。

本讲座详细解释了代理实现的机制及如何声明、实例化和使用代理,并在此基础上引入了单播代理和多播代理、代理链的概念。最后,介绍了事件的实现机制。

下载

返回页首
3、XML与SOAP
XML是一种具有良好开放性、简单性和可扩展性的语言,它能够用来描述非结构化的数据,目前现在广泛的应用于企业应用集成、电子商务和数据交换领域。XML与HTTP是SOAP简单对象访问协议的基础。SOAP主要用于基于Internet环境下的远程过程调用,它使用HTTP协议进行传输,因此较好的解决了跨越企业防火墙的问题,

本讲座主要介绍了XML的概念,语法,XML Schema,XML文档的定义和验证,XML的解析器,XSLT扩展样式语言、XPath等一系列XML相关的内容,并在此基础上简要的介绍了SOAP协议及其实现过程。

下载

返回页首
4、.NET数据库高级应用:数据缓存;连接池管理;分布式事务
数据库访问的性能总是开发人员非常关心的问题。本讲座主要介绍了使用ADO.NET访问数据库的高级应用技术,包括ADO.NET中的连接池管理,各种策略的数据缓存,两种在.NET中实现事务的机制,并讨论了如何实现分布式事务以及优缺点。

下载

返回页首
5、WEB Service高级应用
Web Service是一种新型的Web应用程序。它是自适应、自我描述、模块化的应用程序,这些应用程序可以跨越Web进行发部、定位和调用。Web Service所执行的功能可以是从简单的请求到复杂的商业过程中的任何事。简单的Web Service可以提供股票报价或处理信用卡交易。一旦部署了 Web Service,其它的应用程序可以发现和调用该Web Service。Web Serivce的开发涉及到相当多的技术,包括XML、SOAP、WSDL、UDDI等。

本讲座深入浅出的介绍了Web Service概述和体系结构,如何开发和使用Web Service,以及如何使用Web Service作为数据访问层组件的数据提供者返回复杂的数据类型。最后介绍了Web Service高级开发技术,Web Service Enhancement相关的内容,包括如何对SOAP消息进行加密、签名等。

下载

返回页首
6、NET中的I/O管理:Data Streams and Fils
.NET很好的封装了与数据流和文件操作有关的类,如Stream、FileStream、File、FileInfo等类,并提供了诸如FileSystemWatcher文件系统监控器组件来对文件进行实时的监控与管理。

本讲座主要介绍了.NET中与数据流和文件操作相关的内容,首先介绍了流的概念,接着介绍了如何使用Reader和Writer对象来操作流。最后结合实例对.NET中与文件操作相关的一些基本的类和组件及其使用方法进行了阐述。

下载

返回页首
7、ADO.NET访问Oracle数据库
在ADO.NET中访问Oracle数据库基本的原理与访问SQL Server数据库相同,这个得益于一个专门为Oracle数据库开发的Microsoft .NET Framework Data Provider for Oracle组件,该组件为我们使用.NET访问Oracle数据库提供了极大的方便。 使得那些使用.NET和Oracle的开发人员再也不必使用那个并不十分“专业"的OLEDB来访问Oracle数据库了。

本讲座主要介绍了如何使用Microsoft .NET Framework Data Provider for Oracle组件提供的OracleConnection、OracleCommand、OracleDataReader对象来操作Oracle数据库,并重点介绍了如何访问Oracle数据库中的特殊数据类型以及如何执行Oracle中的储存过程,这个与执行SQL Server的存储过程之间存在相当大的不同。

下载

返回页首
8、.NET 组件开发
组件的开发提供了代码的可重用性,使得应用程序的开发可以像搭积木一样简单和方便。在.NET下可以方便的开发出组件,并可以将其用在控制台应用程序、Windows应用程序、Web应用程序甚至是SmartPhone、Pocket PC上。

本讲座在介绍了.NET Framework开发技术的基础上结合实例介绍了创建和使用.NET组件的步骤和方法。

下载

返回页首
9、.NET序列化
序列化是一个把类的实例转换成一个文件或XML格式的数据流的过程,反序列化则相反。.NET对于序列化的操作进行很好的封装,在.NET下能够非常方便把一个对象序列化成文件或者XML文件。

本讲座主要介绍了序列化的概念、属性,如何把一个或一组具有层次结构的对象序列化成文件,解释了序列化的过程,并举例说明如何执行序列化和反序列化,在讲座的最后,讨论了与序列化相关的安全性的问题。

下载

返回页首
10、与非托管代码交互操作
传统的COM组件和Windows32 API在.NET平台下过时了吗?回答是否定的。许多现存的COM组件和Win32 API在.NET代码中仍然是可用的宝贵资源,.NET对访问这些资源提供了一系列支持,使得这些组件不必重写就能应用于.NET应用程序中。

本讲座全面的介绍了在.NET中调用COM组件和非托管的DLL函数的原理及机制,特别阐述了如何传递结构、类等参数和DLLImport属性的重要选项,并演示了如何向.NET公开COM组件和使用Win32 API。

下载

返回页首
11、.NET Remoting
.NET Remoting提供了一种允许对象通过应用程序域与另一对象进行交互的框架。通过.NET Remoting,两个应用间的通信将变得非常简单,使用上也相当灵活。

本讲座由浅入深的介绍了.NET Remoting的开发技术,首先介绍了Remoting技术的一些基本概念,如远程对象、序列化、客户端和服务器端的激活模式等,其次,详细解释了Remoting的实现机制以及如何使用Remoting技术来设计和实现分布式应用程序,最后通过一个具体的Demo来展示在.NET中实现远程通信是多么的简单。

下载

posted @ 2004-11-04 10:22 sharpen 阅读(193) | 评论 (0)编辑 收藏

2004年11月03日 #

使用异常管理应用程序块Exception Management Application Block

异常管理应用程序块Exception Management Application Block

异常管理应用程序块提供了管理应用程序异常的灵活而又简单的方法。先来看一个最简单使用EMAB的步骤:
(1)添加组件引用:using Microsoft.ApplicationBlocks.ExceptionManagement;
(2)在捕获异常的时候调用异常管理
                        try
                  {
                        throw new Exception ("测试一个异常");
                  }
                  catch(Exception err)
                  {
                        ExceptionManager.Publish (err);
                        MessageBox.Show (err.Message );
                  }
异常err的信息此时被自动记录到系统事件日志中。

就这么简单!

ExceptionManager.Publish执行的时候,首先会到app.config(或者web.config/machine.config)文件里查

找mode属性设置成on的<exceptionManagement>节点,如果没有设置信息,它会调用默认的异常发布类(发布到事

件日志中)。所以,我们使用上面最简单的发布异常的例子里,我们没有必要在配置文件里做任何配置。

当然,我们也可以显式地在app.config文件中声明使用默认异常发布类:

配置文件的格式如下:
<configuration>
  <configSections>
    <section name="exceptionManagement"
             type="Microsoft.ApplicationBlocks.ExceptionManagement
                   .ExceptionManagerSectionHandler,
                   Microsoft.ApplicationBlocks.ExceptionManagement" />
  </configSections>

  <exceptionManagement mode="on/off">
    <publisher mode="on/off" assembly="AssemblyName" type="TypeName"
               exclude="(+)Type;(+)Type" include="(+)Type;(+)Type"
               exceptionFormat="value" /*xml or others*/
               customattr = "value" />
  </exceptionManagement>
</configuration>

我们来解释一下:
<configSections>
            <section name="exceptionManagement"

type="Microsoft.ApplicationBlocks.ExceptionManagement.ExceptionManagerSectionHandler,Microsoft.Ap

plicationBlocks.ExceptionManagement" />
      </configSections>

上面这个配置表示使用ExceptionManagerSectionHander类来读取exceptionManagement节点注册的Publisher类

<exceptionManagement mode="on">           
            <publisher assembly="Microsoft.ApplicationBlocks.ExceptionManagement"

type="Microsoft.ApplicationBlocks.ExceptionManagement.DefaultPublisher" logname="日志文件名"

applicationname="应用程序名" />
      </exceptionManagement>
这个配置信息表示将默认异常发布类注册成应用程序所使用的异常发布类:发布到事件日志的"日志文件名"文

件里(如果不设logname,则使用"应用程序”日志文件)。

我们可以自定义(一个或多个)异常发布类,并把它注册到app.config中,自定义Publisher类主要是要实现IExceptionPublisher接口的Publish方法。这也是很简单的,大家可以查看Exception Management Application block自带的Sample.

下一步就是把一个或多个异常发布类注册到配置文件中:
<exceptionManagement mode="on">
            <publisher assembly="ExceptionManagementQuickStartSamples" type="ExceptionManagementQuickStartSamples.ExceptionPublisher"  exclude="*" include="ExceptionManagementQuickStartSamples.LogonException, ExceptionManagementQuickStartSamples; ExceptionManagementQuickStartSamples.CustomAppException, ExceptionManagementQuickStartSamples" operatorMail="[email protected]"/>                       
            <publisher assembly="ExceptionManagementQuickStartSamples" type="ExceptionManagementQuickStartSamples.ExceptionXMLPublisher" exclude="*" include="+Microsoft.ApplicationBlocks.ExceptionManagement.BaseApplicationException, Microsoft.ApplicationBlocks.ExceptionManagement" exceptionFormat="xml" fileName="c:\QuickStartSamplesExceptionLog.xml"/>
      </exceptionManagement>

OK,就介绍到这吧。

posted @ 2004-11-03 16:02 sharpen 阅读(298) | 评论 (0)编辑 收藏

2004年11月02日 #

Microsoft数据访问应用块 Data Acess Application Block V2 (2) :返回多表结果到同一个DataSet中

如果要使用SqlHelper执行多个SqlCommand并将结果填到同一个DataSet的多个表中,除了在上一篇文章介绍过的使用 ExecuteDataset这个函数以外,还可以使用另一个功能强大的函数:FillDataSet,并且这个方法比ExecuteDataSet更为灵活,比如,您可以指定填充的表的名字,可以在多表之间建立TableRelation,等等。

下面给出一段示例代码:

   DataSet ds=new DataSet ();
   SqlHelper.FillDataset (con,CommandType.Text ,"select * from Customers",ds,new string []{"Customers"});
   dataGrid1.DataSource =ds.Tables ["Customers"];
   SqlHelper.FillDataset (con,CommandType.Text ,"select * from Orders",ds,new string []{"Orders"});
   dataGrid2.DataSource =ds.Tables ["Orders"];



下面是FillDataSet的签名描述:

Executes a command by using a connection string

[C#] FillDataset(string connectionString, CommandType commandType,

         string commandText, DataSet dataset, string[] tableNames)

Executes a command by using a connection string and an array of SqlParameters

[C#] FillDataset(string connectionString, CommandType commandType,

            string commandText, DataSet dataSet, string[] tableNames,

            params SqlParameter[] commandParameters)

Executes a stored procedure by using a connection string

 [C#] FillDataset(string connectionString, string spName, DataSet dataSet,

         string[] tableNames, params object[] parameterValues)

  Executes a command by using a SqlConnection object

  [C#] FillDataset(SqlConnection connection, CommandType commandType,

         string commandText, DataSet dataSet, string[] tableNames)

 Executes a command by using a SqlConnection and an array of SqlParameters

[C#] FillDataset(SqlConnection connection, CommandType commandType,

         string commandText, DataSet dataSet, string[] tableNames, 

         params SqlParameter[] commandParameters)

 Executes a stored procedure by using a SqlConnection object

 [C#] FillDataset(SqlConnection connection, string spName,

         DataSet dataSet, string[] tableNames, params object[] parameterValues)

 Executes a command by using a SqlTransaction

  [C#] FillDataset(SqlTransaction transaction, CommandType commandType,

         string commandText, DataSet dataSet, string[] tableNames)

  Executes a command by using a SqlTransaction and SqlParameters

 [C#] FillDataset(SqlTransaction transaction, CommandType commandType,

         string commandText, DataSet dataSet, string[] tableNames,

         params SqlParameter[] commandParameters)

 Executes a stored procedure by using a SqlTransaction

 [C#] FillDataset(SqlTransaction transaction,

         string spName, DataSet dataSet, string[] tableNames,

         params object[] parameterValues)

posted @ 2004-11-02 16:54 sharpen 阅读(297) | 评论 (0)编辑 收藏

Microsoft数据访问应用块 Data Acess Application Block V2 (1)

Data Access Application Block 将访问 Microsoft SQL Server™ 数据库的性能和资源管理方面的最佳经验封装在一起。您可以很方便地在自己的 .NET 应用程序中将其作为构造块使用,从页减少了需要创建、测试和维护的自定义代码的数量。

个人认为,DAAB最大的好处之一在于DAAB帮助开发者自动管理了数据库的连接. Connection对象是数据库访问组件中最为消耗资源的,如果没有使用using{}关键字或Dispose方法强制释放连接资源,connection对象要等到Garbage Collector启动后才能回收,而如果使用数据访问应用构造块的话,开发者完全不用处理资源的回收问题。

Data Access Application Block 可以帮助您:

调用存储过程或 SQL 文本命令。
指定参数详细信息。
返回 SqlDataReader、DataSet 或 XmlReader 对象。

例如,在引用了 Data Access Application Block 的应用程序中,您可以简单地在一行代码中调用存储过程并生成 DataSet,如下所示:

[Visual Basic]
Dim ds As DataSet = SqlHelper.ExecuteDataset( _
      connectionString, _
      CommandType.StoredProcedure, _
      "getProductsByCategory", _
      new SqlParameter("@CategoryID", categoryID))
 
[C#]
DataSet ds = SqlHelper.ExecuteDataset(
      connectionString,
      CommandType.StoredProcedure,
      "getProductsByCategory",
      new SqlParameter("@CategoryID", categoryID));
 
Microsoft.ApplicationBlocks.Data.dll 程序集包括一个 SqlHelper 类(其中包含用于执行数据库命令的核心功能)和一个 SqlhelperParameterCache 类(提供参数发现和缓存功能)。

SqlHelper 类提供了一组静态方法,可以用来向 SQL Server 数据库发出许多各种不同类型的命令。

SqlHelperParameterCache 类提供命令参数缓存功能,可以用来提高性能。该类由许多 Execute 方法(尤其是那些只运行存储过程的重写方法)在内部使用。数据访问客户端也可以直接使用它来缓存特定命令的特定参数集。

SqlHelper 类提供了六种 Shared (Visual Basic) 或 static (C#) 方法,它们是:ExecuteNonQuery、ExecuteDataset、ExecuteReader、ExecuteScalar 和 ExecuteXmlReader。实现的每种方法都提供一组一致的重载。这提供了一种很好的使用 SqlHelper 类来执行命令的模式,同时为开发人员选择访问数据的方式提供了必要的灵活性。每种方法的重载都支持不同的方法参数,因此开发人员可以确定传递连接、事务和参数信息的方式。类中实现的所有方法都支持以下重载:

[Visual Basic]
Execute* (ByVal connection As SqlConnection, _
          ByVal commandType As CommandType, _
          ByVal CommandText As String)

Execute* (ByVal connection As SqlConnection, _
          ByVal commandType As CommandType, _
          ByVal commandText As String, _
          ByVal ParamArray commandParameters() As SqlParameter) //VB.net 里的ParamArray相当于 C#里的params关键字,即参数数组

Execute* (ByVal connection As SqlConnection, _
          ByVal spName As String, _
          ByVal ParamArray parameterValues() As Object)

/*SqlHelper 类方法的事务型重载不再需要 SqlConnection 参数。在此版本中,连接信息从 SqlTransaction 对象中派生,因此不必在方法签名中包含 SqlConnection 对象参数。*/

Execute* (ByVal transaction As SqlTransaction, _
          ByVal commandType As CommandType, _
          ByVal commandText As String)

Execute* (ByVal transaction As SqlTransaction, _
          ByVal commandType As CommandType, _
          ByVal commandText As String, _
          ByVal ParamArray commandParameters() As SqlParameter)

Execute* (ByVal transaction As SqlTransaction, _
          ByVal spName As String, _
          ByVal ParamArray parameterValues() As Object)

除这些重载以外,除 ExecuteXmlReader 之外的其他方法还提供了另一种重载:允许将连接信息作为连接字符串而不是连接对象来传递,如下面的方法签名所示:

[Visual Basic]
Execute* (ByVal connectionString As String, _
          ByVal commandType As CommandType, _
          ByVal commandText As String)

Execute* (ByVal connectionString As String, _
          ByVal commandType As CommandType, _
          ByVal commandText As String, _
          ByVal ParamArray commandParameters() As SqlParameter)

Execute* (ByVal connectionString As String, _
          ByVal spName As String, _
          ByVal ParamArray parameterValues() As Object)


ExecuteXmlReader 不支持连接字符串,因为:与 SqlDataReader 对象不同,XmlReader 对象在 XmlReader 关闭时没有提供自动关闭连接的方法。如果客户端传递了连接字符串,那么当客户端完成对 XmlReader 的操作后,将无法关闭与 XmlReader 相关联的连接对象。

通过参考 Data Access Application Block 程序集并导入 Microsoft.ApplicationBlocks.Data 命名空间,您可以轻松编写使用任何一种 SqlHelper 类方法的代码,如下面的代码示例所示:

[Visual Basic]
Imports Microsoft.ApplicationBlocks.Data

[C#]
using Microsoft.ApplicationBlocks.Data;
 
导入命名空间后,您可以调用任何 Execute* 方法,如下面的代码示例所示:

[Visual Basic]
Dim ds As DataSet = SqlHelper.ExecuteDataset( _
   "SERVER=(local);DATABASE=Northwind;INTEGRATED SECURITY=True;",
     _
   CommandType.Text, "SELECT * FROM Products")

[C#]
DataSet ds = SqlHelper.ExecuteDataset(
   "SERVER=DataServer;DATABASE=Northwind;INTEGRATED
     SECURITY=sspi;", _
   CommandType.Text, "SELECT * FROM Products");

 
使用 SqlHelperParameterCache 类管理参数
SqlHelperParameterCache 类提供了三种可以用来管理参数的公共共享方法。它们是:

CacheParameterSet。用于将 SqlParameters 数组存储到缓存中。
GetCachedParameterSet。用于检索缓存的参数数组的副本。
GetSpParameterSet。一种重载方法,用于检索指定存储过程的相应参数(首先查询一次数据库,然后缓存结果以便将来查询)。
缓存和检索参数
通过使用 CacheParameterSet 方法,可以缓存 SqlParameter 对象数组。此方法通过将连接字符串和命令文本连接起来创建一个键,然后将参数数组存储在 Hashtable 中。

要从缓存中检索参数,请使用 GetCachedParameterSet 方法。此方法将返回一个 SqlParameter 对象数组,这些对象已使用缓存(与传递给该方法的连接字符串和命令文本相对应)中的参数的名称、值、方向和数据类型等进行了初始化。

注意: 用作参数集的键的连接字符串通过简单的字符串比较进行匹配。用于从 GetCachedParameterSet 中检索参数的连接字符串必须与用来通过 CacheParameterSet 来存储这些参数的连接字符串完全相同。语法不同的连接字符串即使语义相同,也不会被认为是匹配的。

个人认为SqlHelperParameterCache用处不是很大,所以并不想对其进行详细介绍。

如何使用 ExecuteDataset 返回包含多个表的数据集?
通过创建一个可以返回多个行集的存储过程(通过执行多个 SELECT 语句或者对其他存储过程进行嵌套调用),并使用 ExecuteDataset 方法执行该过程,您可以检索包含多个表的数据集。

例如,假设您的数据库包含以下存储过程。

CREATE PROCEDURE GetCategories
AS
SELECT * FROM Categories
GO
CREATE PROCEDURE GetProducts
AS
SELECT * FROM Products
 
您可以创建一个主存储过程来对这些过程进行嵌套调用,如下面的代码示例所示。

CREATE PROCEDURE GetCategoriesAndProducts
AS
BEGIN
  EXEC GetCategories
  EXEC GetProducts
END
 
使用 ExecuteDataset 方法执行此主存储过程将返回一个 DateSet,其中包含两个表:一个表包含分类数据,另一个表包含产品数据。

注意: ExecuteDataset 方法不提供为返回的表指定自定义名称的方法。第一个表的编号始终为 0,名称为 Table,第二个表的编号为 1,名称为 Table1,依此类推。

posted @ 2004-11-02 16:11 sharpen 阅读(449) | 评论 (2)编辑 收藏

决定在blog中讨论一下微软的所有Application Block

Data Access Application Block for .NET v2
Authorization and Profile Application Application Block
Offline Application Application Application Block
Service Aggregation Block
Persistent Asynchronous Invocation Application Block
Caching Application Block
Configuration Management Application Block
Exception Management Application Block
Updater Application Block
User Interface Processes Application Block
Trace Application Block

下面几天,隔几天有空的时候介绍一个吧

posted @ 2004-11-02 15:06 sharpen 阅读(339) | 评论 (1)编辑 收藏

2004年10月25日 #

Business Activity Monitor BAM.xls的DLL Hell问题

打开BAM.xls进行业务活动监视的时候,会报如下错误:

中文版:隐藏模块中编译错误:工具
英文版:"Compile error in hidden module: Utility"

由于BAM Project被密码保护,所以开发人员无法进行调试。

出错原因正是大名鼎鼎的DLL地狱问题,Biztalk 2004 BAM模板中使用的是msado27.tlb(MSDA 2.7)库,如果你安装了最新的MSDA 2.8版本的话,由于两者之间的版本不兼容,BAM无法正常工作。

解决方法是,打开一个新的Excel文件,在VBA IDE中Reference如下文件,C:\Program Files\Common Files\System\ado\msado27.tlb,并把已引用的Microsoft ActiveX Data Object2.8 Library取消,保存这个文件,关闭,重新打开BAM.xls,  这下就work了。

大家可以去try一把试试 ^-^

posted @ 2004-10-25 15:21 sharpen 阅读(218) | 评论 (0)编辑 收藏

2004年10月21日 #

Biztalk Server 2004中在多个接收端口启动工作流

用Web Service发布向导可以将Biztalk 工作流发布成Web Service让供应商或合作伙伴通过HTTP 和SOAP适配器远程调用,与此同时,对于内部的ERP系统,可能更希望通过File适配器调用,如何让一个工作流即可以通过SOAP传入的消息启动,又可以通过File Folder中的传入文件启动呢?

方法还是很简单的,就是在一个Receive Port中添加多个Receive Locations, 并让工作流中的一个Specify Later的逻辑端口绑定到有多个Receive Locations的物理端口,每一个Receive Location都可以启动这个工作流。

你可能感兴趣的:(xml)