zoukankan      html  css  js  c++  java
  • Spring.NET 与 NHibernate

    回到 Spring.NET & NHibernate of C#.NET 技术论坛

    实战C#.NET编程----Spring.NET & NHibernate从入门到精通

      

     

    您可以从以下网址下载最新版:http://tech.bokeecn.com 

    本文中的源代码下载地址:http://tech.bokeecn.com 

     

    作    者:李绿华 (William Lee)

    制作时间:2006-11-30

    版 本 号:V 0.50

    版权声明:未经作者本人许可,任何公司、团体、个人都不得以任何方式复制或抄袭本文内容的部分或全部。

    转载本文请通过以下方式联系作者获得许可。

    邮件:it1630@163.com

    目 录

    实战C#.NET编程----Spring.NET & NHibernate从入门到精通-- 1

    第一章 Visual C# .NET 入门指南-- 3

    一、      C# 简介-- 3

    二、      使用Visual Studio 开始C# 项目-- 3

    步骤 1. 开始项目-- 4

    步骤 2. Hello, World!- 5

    步骤 3. 程序结构-- 7

    步骤 4. 控制台输入-- 8

    步骤 5. 使用数组-- 9

    步骤 6. 文件输入/输出-- 10

    步骤 7. 创建函数-- 13

    步骤 8. 使用调试器-- 15

    小结-- 17

    第二章 面向对像ORM- 18

    一、      什么是ORM- 18

    二、      为什么需要ORM- 19

    三、      流行的ORM框架简介-- 19

    第三章 Spring.NET入门-- 20

    一、      Spring.NET概览-- 20

    二、      第一个Spring.NET的程序-- 22

    第四章 NHibernate入门-- 25

    一、      什么是Nhibernate- 25

    二、      Nhibernate概述-- 25

    三、      第一个NHibernate 程序-- 28

    第五章 Spring.NET 与 NHibernate 的整合-- 34

    一、      建立新的项目(SpringNHibernateSample)- 35

    二、      添加NHibernate程序-- 35

    三、      添加Spring.NET的程序-- 35

    四、      添加Spring.NET为NHibernate的容器配置-- 38

    五、      编写测试程序代码-- 41

    六、      测试并查看结果-- 43

    第六章 深入Spring.NET 与 NHibernate开发-- 43

    第七章 项目实战----办公自动化系统-- 43

    第八章 结束语-- 43

     

     

    第一章 Visual C# .NET 入门指南

    一、      C# 简介

    Visual C# .NET 是 Visual Studio 系列中的最新成员。这种新语言基于 C/C++,但它深化了更容易地使用面向组件编程的发展方向。C/C++ 程序员应该非常熟悉它的语法。

    下面的示例应用程序示范了如何构建一个简单的实现 QuickSort 算法的 C# 项目。它包括了 C# 程序的基本组成部分:读/写控制台和文件、创建函数和使用基本数组。

    这些入门指南并不打算涵盖该编程语言的所有方面。它们只是您探索这种语言的一个起点。我们鼓励您按照本教程的说明执行,因为它包括了 QuickSort 应用程序的各个不同部分。您还可以获得完整的源代码和项目文件。

    建议的要求

    编译此示例应用程序需要 Visual Studio.NET 2003/2005。关于 C/C++ 的知识是有帮助的但不是必需的。

     

    二、      使用Visual Studio 开始C# 项目

    Visual C# .NET 入门指南通过实现一个简单的 QuickSort 算法,带您领略如何构建 Visual C# .NET 项目。

    本节将按以下的步骤让大家一步一步了解Visual C#:

    n        步骤 1. 开始项目

    n        步骤 2. Hello, World!

    n        步骤 3. 程序结构

    n        步骤 4. 控制台输入

    n        步骤 5. 使用数组

    n        步骤 6. 文件输入/输出

    n        步骤 7. 创建函数

    n        步骤 8. 使用调试器

    n        小结

     

    你可以下载 Quicksort_Visual_CSharp_.NET.exe 。里面包含了下面的代码。

    步骤 1. 开始项目

    Visual Studio 中的开发工作以解决方案的形式进行组织,每个解决方案包含一个或多个项目。在本教程中,我们创建的解决方案包含一个 C# 项目。

     

    n        创建一个新项目

    在 Visual Studio .NET 环境中,从菜单中选择 File | New | Project。 

     

     

    在左侧选择 Visual C#Projects,然后在右侧选择 Console Application。

     

    指定项目的名称,然后输入创建项目的位置。Visual Studio 会自动创建项目目录。

     

    单击 OK,那么现在就正式开始了

     

    n        Visual C# 解决方案

    Visual Studio.NET 已经创建了含有一个简单 Visual C# 项目的解决方案。该项目包含两个文件:assemblyinfo.cs 和 class1.cs。

    接下来的几步骤将讨论这些不同的文件以及如何编译该项目。

     

    步骤 2. Hello, World!

    很遗憾,但我们仍然无法抵御这种诱惑……我们还是不得不完成一个基于 C# 的经典"Hello, World!"应用程序,这个应用程序最初是用 C 语言编写的。

    n        修改源代码

    在 Solution Explorer 中双击文件"class1.cs"。可以通过"View"菜单来显示 Solution Explorer。

    更改预生成的模板 (class1.cs),如下面以斜体突出显示的 代码所示。

    using System;

    namespace quicksort

    {

        /// 

        /// Summary description for Class1.

        /// 

        class Class1

        {

            static void Main(string[] args)

            {

                //

                // TODO: Add code to start application here

                //

                Console.WriteLine ("Hello, C#.NET World!");

            }

        }

    }

     

    注意,当您键入代码时,Visual Studio 将为您提示类和函数的名称(因为 .NET 框架发布了这种类型信息)。 

     

     

     

    n        编译应用程序

    既然您已经完成了修改,就可以通过在 Build 菜单中简单地选择 Build 来编译 Visual C# 项目。

     

    来自 C# 编译器的错误和消息会在 Output 窗口中显示。如果没有错误,则可以通过单击 Debug 菜单下的 Start without Debugging 来运行 Hello World 应用程序。 

     

     

    n        程序输出

    在 Visual C# 中运行 Hello World 示例应用程序时,输出结果的屏幕截图如下:

     

     

    n        理解更改

    System.Console 类的 WriteLine() 函数打印传递给它的字符串,其后紧跟一行新的字符。此函数可以接受许多其他数据类型(包括整型和浮点型)的参数。

    在程序加载完成后,控制就传递给 Main() 函数。这就是我们在该过程中插入对 WriteLine() 调用的原因。

     

    步骤 3. 程序结构

    既然我们已经构建了一个简单的 Hello World 应用程序,那么就让我们停下来分析一下 Visual C# 应用程序的基本组成部分。

    n        源代码注释

    字符 “//” 将行的剩余部分标记为一个注释,这样 C# 编译器就会忽略它。另外,/* 和 */ 之间的代码也会被当作注释。

    // This line is ignored by the compiler.

    /* This block of text is also

    ignored by the Visual C# compiler. */

     

    n        Using 指令

    .NET 框架为开发人员提供了许多有用的类。例如,Console 类处理对控制台窗口的输入和输出。这些类是按照层次树的形式组织的。Console 类的完全限定名实际上是 System.Console。其他的类包括 System.IO.FileStream 和 System.Collections.Queue。

    using 指令允许您在不使用完全限定名的情况下引用命名空间中的类。以斜体突出显示的代码应用了 using 指令。

    using System;

    class Class1

    {

        static void Main(string[] args)

        {

            System.Console.WriteLine ("Hello, C#.NET World!");

            Console.WriteLine ("Hello, C#.NET World!");

        }

    }

     

    n        类声明

    与 C++ 或 Visual Basic 不同,Visual C# 中的所有函数都必须封装在一个类中。class 语句声明一个新的 C# 类。就 Hello World 应用程序来说,Class1 类包含一个函数,即 Main() 函数。如果用一个 namespace 块将类的定义括起来,就可以把类组织为诸如 MsdnAA.QuickSortApp 这样的层次。

    在本入门指南中,我们并不打算深入地介绍类,但是我们将为您简要概述为什么类是我们的示例应用程序的一部分。

    n        Main() 函数

    在应用程序加载到内存之后,Main() 函数就会接收控制,因此,应该将应用程序启动代码放在此函数中。传递给程序的命令行参数存储在 args 字符串数组中。

     

    步骤 4. 控制台输入

    现在,我们将继续编写 QuickSort 应用程序。我们需要做的第一件事就是提示用户提供输入和输出文件。

    n        修改源代码

    更改 C# 源文件 (class1.cs),如下面以斜体突出显示的代码所示。其他的差异(如类名)可忽略不计。

    // Import namespaces

    using System;

    // Declare namespace

    namespace MsdnAA

    {

        // Declare application class

        class QuickSortApp

        {

            // Application initialization

            static void Main (string[] szArgs)

            {

                // Describe program function

                Console.WriteLine ("QuickSort C#.NET Sample Application ");

                // Prompt user for filenames

                Console.Write ("Source: ");

                string szSrcFile = Console.ReadLine ();

                Console.Write ("Output: ");

                string szDestFile = Console.ReadLine ();

            }

        }

    }

     

    n        从控制台进行读取

    Console 类的 ReadLine() 方法提示用户输入,并返回输入的字符串。它会自动地为字符串处理内存分配,由于使用了 .NET 垃圾回收器,您不需要做任何释放内存的工作。

     

    n        程序输出

    从菜单中选择 Debug | Start Without Debugging 来运行程序。这是到此为止来自 QuickSort 应用程序的输出的屏幕截图。

     

     

    步骤 5. 使用数组

    在对从输入读取的行进行排序之前,程序需要将其存储到一个数组中。我们将简要讨论可实现对象数组的 .NET 基类的用法。

    n        修改源代码

    更改 C# 源文件 (class1.cs),如下面以斜体突出显示的代码所示。其他的差异(如类名)可忽略不计。

    // Import namespaces

    using System;

    using System.Collections;

    // Declare namespace

    namespace MsdnAA

    {

        // Declare application class

        class QuickSortApp

        {

            // Application initialization

            static void Main (string[] szArgs)

            {

                // Describe program function

                Console.WriteLine ("QuickSort C#.NET Sample Application ");

                // Prompt user for filenames

                Console.Write ("Source: ");

                string szSrcFile = Console.ReadLine ();

                Console.Write ("Output: ");

                string szDestFile = Console.ReadLine ();

                // TODO: Read contents of source file

                ArrayList szContents = new ArrayList ();

            }

        }

    }

     

    n        使用 ArrayList 类

    我们将导入 System.Collections 命名空间,这样我们就可以直接引用 ArrayList。此类实现大小可动态调整的对象数组。要插入新的元素,可以简单地将对象传递到 ArrayList 类的 Add() 方法。新的数组元素将引用原始的对象,而垃圾回收器将处理它的释放。

    string szElement = "insert-me";

    ArrayList szArray = new ArrayList ();

    szArray.Add (szElement);

    要检索现有的元素,请将所需元素的索引传递给 Item() 方法。另外,作为一种简写形式,还可以使用方括号 operator [],它实际上映射到 Item() 方法。

    Console.WriteLine (szArray[2]);

    Console.WriteLine (szArray.Item (2));

    ArrayList 类中还有许多其他方法,但是插入和检索都是我们需要在此示例中使用的。请查阅 MSDN 库以获得完整的参考指南。

     

    步骤 6. 文件输入/输出

    现在,让我们来实现读取输入文件和写入输出文件。我们将每一行读取到一个字符串数组中,然后输出该字符串数组。在下一步中,我们将使用 QuickSort 算法来对该数组进行排序。

    n        修改源代码

    更改 C# 源文件 (class1.cs),如下面以斜体突出显示的代码所示。其他的差异(如类名)可忽略不计。

    // Import namespaces

    using System;

    using System.Collections;

    using System.IO;

    // Declare namespace

    namespace MsdnAA

    {

        // Declare application class

        class QuickSortApp

        {

            // Application initialization

            static void Main (string[] szArgs)

            {

                ... ... ...

                // Read contents of source file

                string szSrcLine;

                ArrayList szContents = new ArrayList ();

                FileStream fsInput = new FileStream (szSrcFile, FileMode.Open,

                   FileAccess.Read);

                StreamReader srInput = new StreamReader (fsInput);

                while ((szSrcLine = srInput.ReadLine ()) != null)

                {

                    // Append to array

                    szContents.Add (szSrcLine);

                }

                srInput.Close ();

                fsInput.Close ();

                // TODO: Pass to QuickSort function

                // Write sorted lines

                FileStream fsOutput = new FileStream (szDestFile,

                    FileMode.Create, FileAccess.Write);

                StreamWriter srOutput = new StreamWriter (fsOutput);

                for (int nIndex = 0; nIndex < szContents.Count; nIndex++)

                {

                    // Write line to output file

                    srOutput.WriteLine (szContents[nIndex]);

                }

                srOutput.Close ();

                fsOutput.Close ();

                // Report program success

                Console.WriteLine (" The sorted lines have been written. ");

            }

        }

    }

     

    n        从源文件进行读取

    使用 FileStream 类打开源文件,然后加入 StreamReader 类,这样我们就可以使用它的 ReadLine() 方法了。现在,我们调用 ReadLine() 方法,直到它返回 null,这表示到达文件结尾。在循环过程中,我们将读取的行存储到字符串数组中,然后关闭这两个对象。

     

    n        写入输出文件

    假设已经用 QuickSort 对字符串数组进行了排序,接下来要做的事情就是输出数组的内容。按照同样的方式,我们将 StreamWriter 对象附加到 FileStream 对象上。这使得我们可以使用 WriteLine() 方法,该方法能够很方便地模仿 Console 类的行为。一旦遍历了数组,我们便可以象前面一样关闭这两个对象。

     

     

    步骤 7. 创建函数

    最后一步就是创建一个函数来在字符串数组中运行 QuickSort。我们将此函数放到应用程序类 QuickSortApp 之中。

    n        修改源代码

    更改 C# 源文件 (class1.cs),如下面以斜体突出显示的 代码所示。其他的差异(如类名)可忽略不计。

    // Import namespaces

    using System;

    using System.Collections;

    using System.IO;

    // Declare namespace

    namespace MsdnAA

    {

        // Declare application class

        class QuickSortApp

        {

            // Application initialization

            static void Main (string[] szArgs)

            {

                ... ... ...

                // Pass to QuickSort function

               QuickSort (szContents, 0, szContents.Count - 1);

                ... ... ...

            }

            // QuickSort implementation

            static void QuickSort (ArrayList szArray, int nLower, int nUpper)

            {

                // Check for non-base case

               if (nLower < nUpper)

                {

                    // Split and sort partitions

                    int nSplit = Partition (szArray, nLower, nUpper);

                    QuickSort (szArray, nLower, nSplit - 1);

                    QuickSort (szArray, nSplit + 1, nUpper);

                }

            }

            // QuickSort partition implementation

            static int Partition (ArrayList szArray, int nLower, int nUpper)

            {

                // Pivot with first element

                int nLeft = nLower + 1;

                string szPivot = (string) szArray[nLower];

                int nRight = nUpper;

                // Partition array elements

                string szSwap;

                while (nLeft <= nRight)

                {

                    // Find item out of place

                    while (nLeft <= nRight)

                    {

                        if (((string) szArray[nLeft]).CompareTo (szPivot) > 0)

                            break;

                        nLeft = nLeft + 1;

                    }

                    while (nLeft <= nRight)

                    {

                        if (((string) szArray[nRight]).CompareTo (szPivot) <= 0)

                            break;

                        nRight = nRight - 1;

                    }

                    // Swap values if necessary

                    if (nLeft < nRight)

                   {

                        szSwap = (string) szArray[nLeft];

                        szArray[nLeft] = szArray[nRight];

                        szArray[nRight] = szSwap;

                        nLeft = nLeft + 1;

                        nRight = nRight - 1;

                    }

                }

                // Move pivot element

                szSwap = (string) szArray[nLower];

                szArray[nLower] = szArray[nRight];

                szArray[nRight] = szSwap;

                return nRight;

            }

        }

    }

     

    n        QuickSort() 函数

    这个函数需要三个参数:对数组的引用、下界和上界。它调用 Partition() 函数将数组分成两部分,其中一部分包含 Pivot 值之前的所有字符串,另一部分包含 Pivot 值之后的所有字符串。然后,它调用自身来对每个部分进行排序。

    上面修改中的注释应该说明了每个代码块的作用。唯一的新概念就是 CompareTo() 方法的使用,该方法是 String 类的成员,并且应该是自说明的。

    n        运行 QuickSort 应用程序

    这一步完成 QuickSort C# 示例应用程序。现在,可以构建项目并运行应用程序。需要提供一个示例文本文件,以供其进行排序。将该文件放在与 EXE 文件相同的目录中。

     

    n        程序输出

    下面是已完成的 QuickSort C# .NET 示例应用程序的输出。可以查看示例输入文件 'example.txt' 和输出文件 'output.txt'

     

     

    步骤 8. 使用调试器

    调试器是诊断程序问题的一个必不可少的工具。我们觉得有必要在本入门指南中对其进行介绍。这最后一步将向您展示如何走查程序和使用诸如 QuickWatch 这样的功能。

    n        设置断点

    当程序在调试器中运行时,断点会暂停程序的执行,从而使开发人员能够控制调试器。要设置断点,请右键单击您想要程序暂停的行,然后单击 InsertBreakpoint,如下所示。

     

    注:带有断点的行以红色突出显示。通过再次右键单击该行并选择 Remove Breakpoint 可以删除断点。

    n        单步调试程序

    既然设置了断点(最好是在前面所示的行中),就让我们在调试器中运行程序。在 Debug 菜单中,选择 Start 而不是同前面一样选择 Start Without Debugging。这样就在调试器中启动了程序,并因而激活了断点。

    一旦程序遇到断点,调试器便会接收程序的控制。这时会有一个箭头指向当前执行的行。

     

    要单步调试一行代码,可以选择 Debug | Step Over 并观察光标是否移到下一行。Debug | Step Into 命令允许您单步执行将要调用的函数。进行两次 Step Over 之后的屏幕如下所示。

     

    如果想要程序在遇到下一个断点、遇到异常或退出之前继续执行,请从菜单中选择 Debug | Continue。

    n        检查变量值

    当您可以控制调试器时,可将鼠标指针移到变量上以获得它的基本值。

     

    您也可以右键单击变量,然后从上下文菜单中选择 QuickWatch。QuickWatch 将为您提供关于某些变量(如 ArrayList 对象)的更多详细信息。

     

    n        其他调试器工具

    Visual Studio 调试器具有许多其他工具(例如 Call Stack 查看器)的功能,可以使用此调试器来查看到此为止调用的函数。还可以获得内存转储和关于进程中线程的信息。我们鼓励您使用这些功能强大的调试工具。

     

     

    小结

    本入门指南旨在帮助您用 Visual Studio 构建一个简单的 C# 项目。它无法进行全面的介绍。我们鼓励您查询关于 C# 和 .NET 的其他资源,以便更多地学习这些技术。在完成本教程之后,您至少有了一个可用的项目,在您研究 Visual C# 时,可以从修改此这些代码开始。

    为了方便起见,我们提供了完整的源程序和项目文件。您可以通过本文档顶部的目录来访问它们。

    n        其他资源

    我们强烈推荐下面这些关于 C# 和 .NET 平台的书籍。它们是开发人员尝试学习这些新技术的有益资源。 

    《C# 高级编程第四版》 英文名为《Professional C# 2005》

    《C#.NET 技术内幕》 英文名为《Microsoft Visual C#.NET 2003 Unleashed》

     

    第二章 面向对像ORM

    ORM的全称是Object/Relation Mapping,即对象/关系映射。ORM也可理解是一种规范,具体的ORM框架可作为应用程序和数据库的桥梁。目前ORM的产品非常多,比如Apache组织下的OJB,Oracle的TopLink,JDO等等。

    一、      什么是ORM

    ORM并不是一种具体的产品,而是一类框架的总称,它概述了这类框架的基本特征:完成面向对象的程序设计语言到关系数据库的映射。基于ORM框架完成映射后,既可利用面向对象程序设计语言的简单易用性,又可利用关系数据库的技术优势。

    面向对象程序设计语言与关系数据库发展不同步时,需要一种中间解决方案,ORM框架就是这样的解决方案。笔者认为,随着面向对象数据库的发展,其理论逐步完善,最终会取代关系数据库。只是这个过程不可一蹴而就,ORM框架在此期间内会蓬勃发展。但随着面向对象数据库的出现,ORM工具会自动消亡。

     

    二、      为什么需要ORM

    在上一节已经基本回答了这个问题,面向对象的程序设计语言,代表了目前程序设计语言的主流和趋势,其具备非常多的优势,比如:

    n        面向对象的建模、操作。

    n        多态、继承。

    n        摒弃难以理解的过程。

    n        简单易用,易理解性。

     

    但数据库的发展并未与程序设计语言同步,而且,关系数据库系统的某些优势,也是面向对象的语言目前无法解决的。比如:

    n        大量数据操作查找、排序。

    n        集合数据连接操作、映射。

    n        数据库访问的并发、事务。

    n        数据库的约束、隔离。

    面对这种面向对象语言与关系数据库系统并存的局面,采用ORM就变成一种必然。

    三、      流行的ORM框架简介

    目前ORM框架的产品非常多,除了各大著名公司、组织的产品外,甚至,其他一些小团队也都有推出自己的ORM框架。目前流行的ORM框架有如下这些产品。

    n        大名鼎鼎的(N)Hibernate:出自Gavin King的手笔,目前最流行的开源ORM框架,其灵巧的设计,优秀的性能,还有丰富的文档,都是其迅速风靡全球的重要因素。

    n        传统的Entity EJB:Entity EJB实质上也是一种ORM技术,这是一种备受争议的组件技术,很多人说它非常优秀,也有人说它一钱不值。事实上,EJB为J2EE的蓬勃发展赢得了极高的声誉,就笔者的实际开发经验而言,EJB作为一种重量级、高花费的ORM技术上,具有不可比拟的优势。但由于其必须运行在EJB容器内,而且学习曲线陡峭,开发周期、成本相对较高,因而限制EJB的广泛使用。

    n        IBATIS:Apache软件基金组织的子项目。与其称它是一种ORM框架,不如称它是一种 “Sql Mapping”框架。相对Hibernate的完全对象化封装,iBATIS更加灵活,但开发过程中开发人员需要完成的代码量更大,而且需要直接编写SQL语句。

    n        Oracle的TopLink:作为一个遵循OTN协议的商业产品,TopLink在开发过程中可以自由下载和使用,但一旦作为商业产品使用,则需要收取费用。可能正是这一点,导致了TopLink的市场占有率。

     

    n        OJB:Apache软件基金组织的子项目。开源的ORM框架,但由于开发文档不是太多,而且OJB的规范一直并不稳定,因此并未在开发者中赢得广泛的支持。

     

    第三章 Spring.NET入门

    一、      Spring.NET概览

    Spring.NET 是一个关注于.NET企业应用开发的应用程序框架。它能够提供宽广范围的功能,例如依赖注入、面向方面编程(AOP)、数据访问抽象, 以及ASP.NET集成等。基于java的spring框架的核心概念和价值已被应用到.NET。Spring.NET 1.0 包含一个完全功能的依赖注入容器和AOP库。后续的发布将包含对ASP.NET、Remoting和数据访问的支持。下图展现出了 Spring .NET的各个模块。具有黑色阴影的模块包含在1.0版本中,其他模块计划在将来的发布中推出。在很多情况下,你可以在我们的下载网站中发现可以工作的计划模块的实现。 

     

    Spring .NET框架概览

    Spring.Core 库是框架的基础, 提供依赖注入功能。Spring.NET中大多数类库依赖或扩展了Spring.Core的功能。IObjectFactory接口提供了一个简单而优雅的工厂模式,移除了对单例和一些服务定位stub写程序的必要。允许你将真正的程序逻辑的配置和依赖的详细情况解耦。作为对IObjectFactory的扩展,IApplicationContext接口也在Spring.Core库中,并且添加了许多企业应用为中心的功能,例如利用资源文件进行文本本地化、事件传播、资源加载等等。

     

    Spring.Aop 库提供对业务对象的面向方面编程(AOP) 的支持。Spring.Aop 库是对Spring.Core库的补充,可为声明性地建立企业应用和为业务对象提供服务提供坚实的基础。

     

    Spring.Web 库扩展了ASP.NET,添加了一些功能,如对ASP.NET页面的依赖注入,双向数据绑定,针对 ASP.NET 1.1的Master pages以及改进的本地化支持。 

     

    Spring.Services库可让你将任何“一般”对象(即没有从其他特殊的服务基类继承的对象)暴露为企业服务或远程对象,使得.NET Web services 获得依赖注入的支持,并覆盖属性元数据。此外还提供了对Windows Service的集成。

     

    Spring.Data 库提供了数据访问层的抽象,可以被多个数据访问提供者(从ADO.NET 到多个ORM 提供者)应用。它还包含一个对ADO.NET的抽象层,移除了为ADO.NET编写可怕的编码和声明性的事务管理的必要。

     

    Spring.ORM库提供了对常见对象关系映射库的的集成,提供了一些功能,比如对声明性事务管理的支持。

    二、      第一个Spring.NET的程序

    n        建立项目

    项目名称为:SpringSample,NameSpace为“OKEC.Sample.Spring”。

     

    n        添加HelloTest类

    HelloTest.cs

    using System;

    namespace OKEC.Sample.Spring

    {

        /// <summary>

        /// HelloTest 的摘要说明。

        /// </summary>

        public class HelloTest

        {

            public HelloTest()

            {

                  //

                  // TODO: 在此处添加构造函数逻辑

                  //

            }

            public void Test()

            {

                  Console.WriteLine("This is Spring.NET Sample Test!");

                  Console.WriteLine("Please press Enter close the windows!");

                  Console.ReadLine();//让程序停留,回车关闭。

            }

        }

    }

     

    n        添加Spring.NET的配置文件

    文件名:Spring_bean.xml,属性设置为:嵌入的资源/ Embedded Resource

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

    <objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

            xsi:schemaLocation="http://www.springframework.net 

            http://www.springframework.net/xsd/spring-objects.xsd">

      <object id="Hello" type="OKEC.Sample.Spring.HelloTest,SpringSample" />

    </objects>

     

    n        建立Spring.NET的容器初始化对像

    SpringContext.cs

    using System;

    using Spring.Core;

    using Spring.Aop;

    using System;

    using Spring.Core;

    using Spring.Aop;

    using Spring.Context;

    using Spring.Context.Support;

    namespace OKEC.Sample.Spring

    {

        /// <summary>

        /// SpringFactory 的摘要说明。

        /// </summary>

        public class SpringContext

        {

            public SpringContext()

            {

                  //

                  // TODO: 在此处添加构造函数逻辑

                  //

            }

            private static bool isInit = false;

            private static IApplicationContext context;

            public static void init()

            {

                  string[] xmlFiles = new string[1];            

                  xmlFiles[0] = "assembly://SpringSample/OKEC.Sample.Spring/Spring_bean.xml";

                  context = new XmlApplicationContext(xmlFiles);

                  isInit = true;

            }

            public static IApplicationContext Context

            {

                  get{

                      if(!isInit)

                      {

                          init();

                      }

                      return context;

                  }

            }

        }

    }

     

    n        添加启动程序

    StartMain.cs

    using System;

    namespace OKEC.Sample.Spring

    {

        /// <summary>

        /// StartMain 的摘要说明。

        /// </summary>

        public class StartMain

        {

            public StartMain()

            {

                  //

                  // TODO: 在此处添加构造函数逻辑

                  //

            }

            [STAThread]

            static void Main() 

            {

                  //Startup Spring Content

                  SpringContext.init();

     

                  //Test Spring IOC

                  HelloTest test = (HelloTest)SpringContext.Context.GetObject("Hello");

                  test.Test();

            }

        }

    }

    n        运行程序

    结果为:

    This is Spring.NET Sample Test!

    Please press Enter close the windows!

    你的第一个Spring.NET的程序成功了!

    第四章 NHibernate入门

    一、      什么是Nhibernate

    NHibernate 是一个基于.Net 的针对关系型数据库的对象持久化类库。Nhibernate 来源于非常优秀的基于Java的Hibernate 关系型持久化工具。

    NHibernate 从数据库底层来持久化你的.Net 对象到关系型数据库。NHibernate 为你处理这些,远胜于你不得不写SQL去从数据库存取对象。你的代码仅仅和对象关联,NHibernat 自动产生SQL语句,并确保对象提交到正确的表和字段中去。

    二、      Nhibernate概述

    对NHibernate体系结构的非常高层的概览:

     

    这幅图展示了NHibernate使用数据库和配置文件数据来为应用程序提供持久化服务(和持久化的对象)。 

    我们试图显示更多NHibernate运行时体系结构的细节。 但挺不幸的,NHibernate是比较灵活的并且提供了好几种不同的运行方式。我们展示一下两种极端情况。轻型体系中,应用程序自己提供ADO.NET连接,并且自行管理事务。这种方式使用了NHibernate API的一个最小子集。 

     

    全面解决体系中,对于应用程序来说,所有的底层ADO.NET API都被抽象了,NHibernate会替你照管所有的细节。

     

     

    下面是图中一些对象的定义:

    SessionFactory (NHibernate.ISessionFactory) 

    对属于单一数据库的编译过的映射文件的一个线程安全的,不可变的缓存快照。它是Session的工厂,是ConnectionProvider的客户。可以持有一个可选的(第二级)数据缓存,可以在进程级别或集群级别保存可以在事物中重用的数据。

    会话,Session (NHibernate.ISession) 

    单线程,生命期短促的对象,代表应用程序和持久化层之间的一次对话。封装了一个ADO.NET连接。也是Transaction的工厂。保存有必需的(第一级)持久化对象的缓存,用于遍历对象图,或者通过标识符查找对象。

    持久化对象(Persistent)及其集合(Collections) 

    生命期短促的单线程的对象,包含了持久化状态和商业功能。它们可能是普通的对象,唯一特别的是他们现在从属于且仅从属于一个Session。一旦Session被关闭,他们都将从Session中取消联系,可以在任何程序层自由使用(比如,直接作为传送到表现层的DTO,数据传输对象)。 

    临时对象(Transient Object)及其集合(Collection) 

    目前没有从属于一个Session的持久化类的实例。他们可能是刚刚被程序实例化,还没有来得及被持久化,或者是被一个已经关闭的Session所实例化的。 

    事务Transaction (NHibernate.ITransaction) 

    (可选) 单线程,生命期短促的对象,应用程序用它来表示一批工作的原子操作。是底层的ADO.NET事务的抽象。一个Session某些情况下可能跨越多个Transaction 事务。 

    ConnectionProvider (NHibernate.Connection.ConnectionProvider) 

    (可选)ADO.NET连接的工厂。从底层的IDbConnection抽象而来。对应用程序不可见,但可以被开发者扩展/实现。 

    TransactionFactory (net.sf.hibernate.TransactionFactory) 

    (可选)事务实例的工厂。对应用程序不可见,但可以被开发者扩展/实现。 

    在上面的轻型结构中,程序没有使用Transaction / TransactionFactory 或者ConnectionProvider API,直接和ADO.NET对话了

     

    三、       第一个NHibernate 程序

    任何熟悉Hibernate的人会发现这篇指南和Glen Smith 的 A Hitchhiker's Guide to Hibernate 非常相近。这里的内容正是基于他的指南,因此所有的感谢都应该给与他。

     

    NHibernate的文档并非每处都和Hibernate的文档一致。然而,项目的相似应该能使读者通过读Hibernate的文档来很好的理解NHibernate如何工作。

     

    这篇文档意在让你尽可能快的开始使用NHibernate。它将介绍如何持久化一个简单的对象到一张表里。想得到更多的复杂的例子,可以参考NUnit测试及附带代码。

    我们将进行以下步骤。

    1.新建一个将要持久化.Net对象的表

    2.构建一个可以让NHibernate知道如何持久化对象属性的映射文件

    3.构建一个需要被持久化的.Net类

    4.构建一个存放NHibernater的配置文件的对像

    5.使用NHibernate的API测试你的第一个NHibernate程序

     

    n        新建项目

    项目名称为:NHibernateSample,名字空间:OKEC.Sample.NHibernate

    n        建立数据表

    数据库为SQLServer2000,表名为:my_users

    if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[my_users]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)

        drop table [dbo].[my_users]

        GO

        CREATE TABLE [dbo].[my_users] (

        [LogonId] [varchar] (50) COLLATE Chinese_PRC_CI_AS NOT NULL ,

        [UserName] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,

        [Password] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,

        [EmailAddress] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,

        [LastLogon] [datetime] NULL 

        ) ON [PRIMARY]

        GO

        ALTER TABLE [dbo].[my_users] ADD 

        CONSTRAINT [PK_my_users] PRIMARY KEY  CLUSTERED 

        (

        [LogonId]

        )  ON [PRIMARY] 

        GO

     

    n        建立XML对像映射文件

    现在我们有数据表和需要去映射它的.Net类。我们需要一种方式去让NHibernate知道如何从一个映射到另一个。这个任务依赖于映射文件来完成。最易于管理的办法是为每一个类写一个映射文件,如果你命名它是User.hbm.xml并且把它放在和类的同一个目录里,NHiberante将会使得事情简单起来。下面是User.hbm.xml的例子:

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

    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">

        <class name=" OKEC.Sample.NHibernate.NHibernateTest.User,NHibernateSample" table="my_users">

            <id name="Id" column="LogonId" type="String" length="20">

            <generator class="assigned" />

            </id>        

            <property name="UserName" column="UserName" type="String" length="40"/>

            <property name="Password" column="Password" type="String" length="20"/>

            <property name="EmailAddress" column="EmailAddress" type="String" length="40"/>

            <property name="LastLogon" column="LastLogon" type="DateTime"/>

        </class> 

    </hibernate-mapping>

    注意事项:在Visual Studio 2003/2005中要将此文件的属性设置为“嵌入的资源”(Embedded Resource)

    n        建立对像

    对像定义:User.cs

    using System;

    namespace OKEC.Sample.NHibernate.NHibernateTest

    {

        /// <summary>

        /// Summary description for User.

        /// </summary>

        public class User

        {

            private string id;

            private string userName;

            private string password;

            private string emailAddress;

            private DateTime lastLogon;

            public User()

            {

            }

            public string Id 

            {

                  get { return id; }

                  set { id = value; }

            }

            public string UserName 

            {

                  get { return userName; }

                  set { userName = value; }

            }

            public string Password 

            {

                  get { return password; }

                  set { password = value; }

            }

            public string EmailAddress 

            {

                  get { return emailAddress; }

                  set { emailAddress = value; }

            }

            public DateTime LastLogon 

            {

                  get { return lastLogon; }

                  set { lastLogon = value; }

            }

        }

    }

     

    n        编写Nhibernate的初始化配置程序

    程序名:MyConfiguration.cs

    using System;

    using NHibernate.Cfg;

    namespace OKEC.Sample.NHibernate.NHibernateTest

    {

        /// <summary>

        /// MyConfiguration 的摘要说明。

        /// </summary>

        public class MyConfiguration

        {

            public MyConfiguration()

            {

                  //

                  // TODO: 在此处添加构造函数逻辑

                  //

            }

            public Configuration GetConfig()

            {

                  try

                  {

                      Configuration cfg = new Configuration();              cfg.SetProperty("hibernate.connection.provider","NHibernate.Connection.DriverConnectionProvider");

                      //请修改此行中的SQLServer的配置

                      cfg.SetProperty("hibernate.connection.connection_string","Data Source=192.168.88.15;Database=liluhua;User ID=sa;Password=sa;Trusted_Connection=False");

                      cfg.SetProperty("hibernate.dialect","NHibernate.Dialect.MsSql2000Dialect");

                      cfg.SetProperty("hibernate.connection.driver_class","NHibernate.Driver.SqlClientDriver");

                      cfg.AddAssembly("NHibernateSample");

                      return cfg;

                  }

                  catch(Exception ex)

                  {

                      Console.WriteLine(ex.Message);

                      Console.WriteLine(ex.StackTrace);

                  }

                  return null;

            }

        }

    }

    n        编写调用程序

    准备好上面的一切,我们就可以开始编辑启动程序,来测试你的第一个Nhibernate程序了。

    程序名:UserFixture.cs

    using System;

    using System.Collections;

    using NHibernate;

    using NHibernate.Cfg;

    using NHibernate.Expression;

    namespace OKEC.Sample.NHibernate.NHibernateTest

    {

        /// <summary>

        /// UserFixture 的摘要说明。

        /// </summary>

        public class UserFixture

        {

            public UserFixture()

            {

                  //

                  // TODO: 在此处添加构造函数逻辑

                  //

            }

            public void ValidateQuickStart() 

            {

                  try

                  {

                      //得到NHibernate的配置

                      MyConfiguration config = new MyConfiguration();

                      Configuration cfg = config.GetConfig();

     

                      ISessionFactory factory = cfg.BuildSessionFactory();

                      ISession session = factory.OpenSession();

                      ITransaction transaction = session.BeginTransaction();

     

                      User newUser = null;

                      try

                      {

                          newUser = (User)session.Load(typeof(User), "joe_cool");

                      }

                      catch

                      {

                      }

                      if(newUser==null)

                      {

                          newUser = new User();

                          newUser.Id = "joe_cool";

                          newUser.UserName = "Joseph Cool";

                          newUser.Password = "abc123";

                          newUser.EmailAddress = "joe@cool.com";

                          newUser.LastLogon = DateTime.Now;

     

                          // Tell NHibernate that this object should be saved

                          session.Save(newUser);

                      }            

     

                      // commit all of the changes to the DB and close the ISession

                      transaction.Commit();

                      session.Close();

     

                      // open another session to retrieve the just inserted user

                      session = factory.OpenSession();

     

                      User joeCool = (User)session.Load(typeof(User), "joe_cool");

     

                      // set Joe Cool's Last Login property

                      joeCool.LastLogon = DateTime.Now;

     

                      // flush the changes from the Session to the Database

                      session.Flush();

     

                      IList recentUsers = session.CreateCriteria(typeof(User))

                          .Add(Expression.Gt("LastLogon", new DateTime(2004, 03, 14, 20, 0, 0)))

                          .List();

                      foreach(User user in recentUsers)

                      {

                          //Assert.IsTrue(user.LastLogon > (new DateTime(2004, 03, 14, 20, 0, 0)) ); 

                          Console.WriteLine(user.UserName);

                          Console.WriteLine(user.Password);

                      }

                      session.Close();

                  }

                  catch(Exception ex)

                  {

                      Console.WriteLine(ex.Message);

                      Console.WriteLine(ex.StackTrace);

                  }

                  Console.ReadLine();

            }

        }

    }

    n        测试你的程序

    如果运行后没有出错,显示了结果,说明你的第一个NHibernate程序成功了。

    Joseph Cool

    abc123

     

    第五章 Spring.NET 与 NHibernate 的整合

    我们成功的运行了自己的第一个Spring.NET程序和第一个NHibernate程序。下面我们将上面的程序整合到一个项目中来。让Spring.NET的容器来管理NHibernate。

    一、      建立新的项目(SpringNHibernateSample)

    项目名称为:SpringNHibernateSample 名字空间:OKEC.Sample

    二、      添加NHibernate程序

    将NHibernateSample项目的User.cs、User.hbm.xml加入的新的项目中。

    并修改User.hbm.xml,将其中的

    <class name=" OKEC.Sample.NHibernate.NHibernateTest.User,NHibernateSample"

     table="my_users">

    改为:

    <class name=" OKEC.Sample.NHibernate.NHibernateTest.User,SpringNHibernateSample"

     table="my_users">

     

    三、      添加Spring.NET的程序

    n        首先,需要将SpringSample项目中的HelloTest.cs、Spring_bean.xml、SpringContext.cs加入到新的项目,并修改其中有用到程序集相关的地方。

    如将Spring_bean.xml中的:

    <object id="Hello" type="OKEC.Sample.Spring.HelloTest,SpringSample" />

    改为:

    <object id="Hello" type="OKEC.Sample.Spring.HelloTest,SpringNHibernateSample" />

     

    n        然后,添加一个为NHibernate提供DbProvider的实现类,此类实现了Spring.Data.Common.IDbProvider接口,为NHibernate提供DbProvider所需的链接字串(ConnectionString)。

    using System;

    using Spring.Data.Common;

    namespace OKEC.Sample.Spring

    {

        /// <summary>

        /// SQLPriv 的摘要说明。

        /// </summary>

        public class SQLProvider:IDbProvider

        {

            public SQLProvider()

            {

                  //

                  // TODO: 在此处添加构造函数逻辑

                  //

            }

            #region IDbProvider 成员

            public System.Data.IDbConnection CreateConnection()

            {

                  // TODO:  添加 SQLPriv.CreateConnection 实现

                  return null;

            }

            public string CreateParameterName(string name)

            {

                  // TODO:  添加 SQLPriv.CreateParameterName 实现

                  return null;

            }

            public System.Data.IDbDataParameter CreateParameter()

            {

                  // TODO:  添加 SQLPriv.CreateParameter 实现

                  return null;

            }

            private string _connectionString="";

            public string ConnectionString

            {

                  get

                  {

                      // TODO:  添加 SQLPriv.ConnectionString getter 实现

                      return _connectionString;

                  }

                  set

                  {

                      _connectionString = value;

                      // TODO:  添加 SQLPriv.ConnectionString setter 实现

                  }

            }

            public string ExtractError(Exception e)

            {

                  // TODO:  添加 SQLPriv.ExtractError 实现

                  return null;

            }

            public System.Data.IDbDataAdapter CreateDataAdapter()

            {

                  // TODO:  添加 SQLPriv.CreateDataAdapter 实现

                  return null;

            }

            public bool IsDataAccessException(Exception e)

            {

                  // TODO:  添加 SQLPriv.IsDataAccessException 实现

                  return false;

            }

            public System.Data.IDbCommand CreateCommand()

            {

                  // TODO:  添加 SQLPriv.CreateCommand 实现

                  return null;

            }

            public object CreateCommandBuilder()

            {

                  // TODO:  添加 SQLPriv.CreateCommandBuilder 实现

                  return null;

            }

            public IDbMetadata DbMetadata

            {

                  get

                  {

                      // TODO:  添加 SQLPriv.DbMetadata getter 实现

                      return null;

                  }

            }

            #endregion

        }

    }

     

    n        最后,添加一个Spring.Data.NHibernate对NHibernate的封装对像,此对像实现对User对像数据操作,继承自

    Spring.Data.NHibernate.Support.HibernateDaoSupport。

    using System;

    using System.Collections;

    using Spring.Data.NHibernate.Support;

    namespace OKEC.Sample.NHibernate.NHibernateTest

    {

        /// <summary>

        /// UserDao 的摘要说明。

        /// </summary>

        public class UserDao : HibernateDaoSupport

        {

            public UserDao()

            {    //

                  // TODO: 在此处添加构造函数逻辑

                  //

            }

            public bool SaveObject(User user)

            {

                  HibernateTemplate.Save(user);

                return true;

            }

            public bool DeleteObject(User user)

            {

                  HibernateTemplate.Delete(user);

                  return true;

            }

            public bool UpdateObject(User user)

            {

                  HibernateTemplate.Update(user);

                  return true;

            }

            public IList GetAllObjectsList()

            {

                  return HibernateTemplate.LoadAll(typeof(User));

            }

            public User Load(Object ID)

            {

                  return (User)HibernateTemplate.Load(typeof(User),ID);

            }

        }

    }

     

    四、      添加Spring.NET为NHibernate的容器配置

    现在就可以在Spring.NET的容器中添加Nhibernate的配置了。

    如下Spring_nhibernate.xml:

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

    <objects xmlns='http://www.springframework.net'>

     

     <!-- NHibernate初始化的 -->

    <object id="DbProvider" type="OKEC.Sample.Spring.SQLProvider,SpringNHibernateSample">

        <property name="ConnectionString" value="Data Source=192.168.88.15;Database=liluhua;User ID=sa;Password=sa;Trusted_Connection=False"/>

    </object>

     

    <object id="SessionFactory" 

    type="Spring.Data.NHibernate.LocalSessionFactoryObject, Spring.Data.NHibernate">

        <property name="DbProvider" ref="DbProvider"/>

        <property name="MappingAssemblies">

            <list>

                  <value>SpringNhibernateSample</value>

            </list>

        </property>

        <property name="HibernateProperties">

            <dictionary>

                  <entry 

    key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider"/> 

                  <!--entry 

    key="hibernate.connection.connection_string" value="Data Source=192.168.188.188;Database=Test;User ID=satest;Password=satest;Trusted_Connection=False"/--> 

                  <entry key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Dialect"/> 

                  <entry 

    key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver"/>  

            </dictionary>

        </property> 

     </object> 

     

     <object id="HibernateTransactionManager" type="Spring.Data.NHibernate.HibernateTransactionManager, Spring.Data.NHibernate"> 

        <property name="DbProvider" ref="DbProvider"/>

        <property name="sessionFactory" ref="SessionFactory"/>

     </object>

     

     <object id="TransactionInterceptor" 

    type="Spring.Transaction.Interceptor.TransactionInterceptor, Spring.Data">

        <property name="TransactionManager" ref="HibernateTransactionManager"/>

        <property name="TransactionAttributeSource">

            <object 

    type="Spring.Transaction.Interceptor.AttributesTransactionAttributeSource, Spring.Data"/> 

        </property> 

     </object>

     

     <!-- 以下是业务相关的 -->

     <object id="UserDao"

     type="OKEC.Sample.NHibernate.NHibernateTest.UserDao, SpringNHibernateSample">

            <property name="SessionFactory" ref="SessionFactory"/>

     </object>

    </objects>

     

    我们现在对上面的加以细解:

    下面这几行,是配置Nhibernate所需的数据库的DbProvider

    <object id="DbProvider" type="OKEC.Sample.Spring.SQLProvider,SpringNHibernateSample">

        <property name="ConnectionString" value="Data Source=192.168.88.15;Database=liluhua;User ID=sa;Password=sa;Trusted_Connection=False"/>

    </object>

     

    下面的是对Nhibernate的SessionFactory的封装的对像的定义

    <object id="SessionFactory" 

    type="Spring.Data.NHibernate.LocalSessionFactoryObject, Spring.Data.NHibernate">

        <property name="DbProvider" ref="DbProvider"/>

        <property name="MappingAssemblies">

            <list>

                  <value>SpringNhibernateSample</value>

            </list>

        </property>

        <property name="HibernateProperties">

            <dictionary>

                  <entry key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider"/> 

                  <!--entry key="hibernate.connection.connection_string" value="Data Source=192.168.188.188;Database=Test;User ID=satest;Password=satest;Trusted_Connection=False"/--> 

                  <entry key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Dialect"/> 

                  <entry key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver"/>  

            </dictionary>

        </property> 

     </object>

     

    下面的是对Nhibernate中的Transaction封装对像

    <object id="HibernateTransactionManager" type="Spring.Data.NHibernate.HibernateTransactionManager, Spring.Data.NHibernate"> 

        <property name="DbProvider" ref="DbProvider"/>

        <property name="sessionFactory" ref="SessionFactory"/>

     </object>

     

     <object id="TransactionInterceptor" type="Spring.Transaction.Interceptor.TransactionInterceptor, Spring.Data">

        <property name="TransactionManager" ref="HibernateTransactionManager"/>

        <property name="TransactionAttributeSource">

            <object type="Spring.Transaction.Interceptor.AttributesTransactionAttributeSource, Spring.Data"/> 

        </property> 

     </object>

     

    下面是对NHibernate业务操作对像的定义

    <object id="UserDao" 

    type="OKEC.Sample.NHibernate.NHibernateTest.UserDao, SpringNHibernateSample">

            <property name="SessionFactory" ref="SessionFactory"/>

     </object>

     

    五、      编写测试程序代码

    一切准备就绪,我们就可以编写测试程序的代码了。

    如下:StartMain.cs

    using System;

    using System.Collections;

    using OKEC.Sample.NHibernate.NHibernateTest;

    namespace OKEC.Sample.Spring

    {

        /// <summary>

        /// StartMain 的摘要说明。

        /// </summary>

        public class StartMain

        {

            public StartMain()

            {  //

                  // TODO: 在此处添加构造函数逻辑

                  //

            }

            [STAThread]

            static void Main() 

            {        

                  //Startup Spring & NHibernate Content

                  SpringContext.init();

     

                  //Test Spring IOC

                  HelloTest test = (HelloTest)SpringContext.Context.GetObject("Hello");

                  test.Test();

     

                  //Test Spring & NHibernate

                  UserDao dao = SpringContext.Context.GetObject("UserDao") as UserDao;

                  User newUser = null;

                  try

                  {

                      newUser = dao.Load("joe_cool");

                  }

                  catch

                  {}

                  if(newUser==null)

                  {

                      newUser = new User();

                      newUser.Id = "joe_cool";

                      newUser.UserName = "Joseph Cool";

                      newUser.Password = "abc123";

                      newUser.EmailAddress = "joe@cool.com";

                      newUser.LastLogon = DateTime.Now;

                      // Tell NHibernate that this object should be saved

                      dao.SaveObject(newUser);

                  }

                  User joeCool = dao.Load("joe_cool");

                  // set Joe Cool's Last Login property

                  joeCool.LastLogon = DateTime.Now;

                  // flush the changes from the Session to the Database

                  dao.UpdateObject(joeCool);

                  IList recentUsers = dao.GetAllObjectsList();

                  foreach(User user in recentUsers)

                  {

                      //Assert.IsTrue(user.LastLogon > (new DateTime(2004, 03, 14, 20, 0, 0)) ); 

                      Console.WriteLine(user.UserName);

                      Console.WriteLine(user.Password);

                  }

                  Console.ReadLine();//让程序停留,回车关闭。

            }

        }

    }

    六、      测试并查看结果

    如果你看到了以下的输出结果,说明你已经成功了!

    This is Spring.NET Sample Test!

    Please press Enter close the windows!

    Joseph Cool

    abc123

     

    第六章 深入Spring.NET 与 NHibernate开发

    待写

    第七章 项目实战----办公自动化系统

    待写

     

    第八章 结束语

    待写

     

     

  • 相关阅读:
    Shell parameter expansion
    前端知识的一些总结
    IT增值服务实践心得体会:企业客户的钱比个人客户好赚得多
    IT增值服务实践心得体会:企业客户的钱比个人客户好赚得多
    电子商务网站的设计与实现(一):当前的一些购物体验和开发期望
    电子商务网站的设计与实现(一):当前的一些购物体验和开发期望
    个人官网第7次升级:全文搜索闪亮登场
    个人官网第7次升级:全文搜索闪亮登场
    关于开发简易搜索引擎的一些总结和思考
    雷观(十六):以习近平为首的新一届领导集体,大权在握,做事很有信心
  • 原文地址:https://www.cnblogs.com/anbylau2130/p/3291428.html
Copyright © 2011-2022 走看看