微软企业库5.0 学习

  • Post author:
  • Post category:其他




微软企业库

5.0


学习之路


——


第一步、基本入门



一、什么是企业库?


企业库包含一系列应用程序模块和核心架构。这些高复用的组件旨在帮助开发者解决一些共同的企业开发问题。  企业库同时提供高可配置的特性,使我们管理重复的工作更加容易,例如我们知道的在应用的很多地方发生的横切关注点。包括像日志记录、缓存、异常管理等。另外,它提供的依赖注入容器能够简化和分解你的设计,使他们更加可实验和容易理解,帮助你创建更加高性能的设计和各种应用。  二、使用企业库的

3


个简单步骤:

1.

引用和配置你需要的程序集。

2.

通过企业库配置应用。

3.

在你的代码中创建和使用企业库对象。

三、企业库的好处:  应用模块帮助解决开发者从一个项目到另一个项目面对的共同问题。他们的设计封装了微软推荐的做法,这些都是基于微软框架的应用开发。例如,数据访问应用模块提供了对

ADO.NET


访问最频繁使用的特征。在某些情况下,应用模块还添加了一些基础类库没有直接提供的相关功能。

四、企业库的目标:  1.

一致。所有的企业库模块都坚持一致的设计模式和实现方式。

2.

可扩展性。所有的应用模块包括定义扩展点,允许开发人员通过添加自己的代码定制应用模块的行为。

3.

易用性。企业库提供了许多实用性的东西,包括一个图形化配置工具,简单的安装过程,完成的文档和示例。

4.

集成。企业库应用模块被设计得能够一起很好的工作,并且也被这样测试过。但是你不必一起使用他们。我们可以单独使用这些应用模块,同时这些应用模块之间也有些依赖,比如在企业库核心和


Unity


中的一些通用组件。


上面是企业库的基本概念,理解了企业库的相关知识后,我们可以开始来安装企业库了


1

、下载地址:


点我进入下载页面(不是直接下载)

,安装后就可以使用了。


这次

5.0


相比


4.1


的最大改动就是整个配置工具采用了


WPF


重新构建和实例化和管理对象生命周期的全依赖注入的实现,同时支持


VS2008SP1





VS2010


,话说虽然这次的配置工具变化挺大的,但是一旦熟悉了就觉得比


4.1


的好,因为可以清楚的看见每个模块的之间的依赖关系。


一、

Unity


和对象生成器的整合

在这个版本中,用于创建对象的基本技术是一个单一的依赖注入容器,默认的是

Unity


。你可以使用容器生成企业库对象的实例并注入到其他的对象。 企业库提供一个标准的接口从


Unity


容器中来获得定义在企业库配置中的对象的实例,如


SqlDatabase





LogWriter.


另外,注入友好的实例门面处理静态门面之外是有效的,因为静态门面不能用注入,但是为了向后兼容以前的版本而存在。在本版本中的示例中都是用依赖注入,但是以前版本中是用的静态工厂类和静态门面在这个版本中还是支持的。对象生成器,一个低版本的依赖注入机制在这个版本中被归入


Unity


中,在项目中不再需要单独引用对象生成器集。

支持

Unity


容器,必须引用一个被包含在企业库中的


Microsoft.Practices.ServiceLocation


程序集。如果要使用一个第


3


方的依赖注入容器,必须直接实现


IServiceLocator


接口或者通过适配器实现。


二、影响所有模块的变化

:

1.

在企业库中主要修正是使用依赖注入机制。所用的应用模块以及核心系统都是用依赖注入机制,并使用


Unity


作为默认的依赖注入容器,来创建和管理企业库对象。

2.

自主容器的实现通过实现


Common Service Locator


项目提供的


IServiceLocator


接口来完成。

3.

由于错误配置引发的错误将提供更多有用的错误信息。

4.

配置系统公开了一个


fluent


接口,用来为单个对象或整个应用创建和填充配置源。


fluent API


使得为各种情景创建配置源更加容易。

5.ConfigurationView

类被删除


.

6.

一些配置元素有默认值


,


可能不同于以前版本的隐式默认值


.

7.

企业库现在允许你通过另一个配置文件合成一个混合配置文件


.

8.

可以可通过不同的配置文件读取不同的配置信息


.

9.

企业库不支持


XAML


浏览器应用程序(


XBAP).

10.WmiEnabled

标志为了像前兼容仍然存在企业库中


,


但是在


5.0


中是被忽略的


,


而且将来会被删除


.

11.

改进式的安装允许你只安装部分应用模块及配置工具


.

12.

在以前版本中要做统一集成,必须添加核心企业库的扩展和每个模块的扩展。现在如果你只需要直接访问容器,那么只有核心扩展是必须的。单独模块将自动支持。

旧的功能为了保持像前兼容仍然保留,但已经不起作用。  13.FileConfigurationSource.Save

的签名已经改变,参数由


3


个变为


2


个。

14.

快速入门不再包含在主安装程序中。


三、

Breaking


变化:

1.

企业库现在抛出了一个配置错误


ActivationException


,之前是


System.Configuration.ConfigurationErrorsException


。这包括试着解决没有配置信息错误的一个实例提供者。

2.

以前版本在获取应用模块错误时抛出


BuildFailedException


错误,现在对于所有的应用模块都抛出


ActivationException

3 .

之前的版本,在讲一个空源传到容器来调用容器的时候,会抛出


ArgumentNullException


,现在抛出


NullReferenceException

4.ObjectBuilder2

不再是一个单独的程序集,而是集成到了


Unity


集合中,在项目中也不需要引用


ObjectBuilder2.dll





5.WMI

支持已经从企业库中删除,除了在


logging


模块中的


WMI


跟踪监听器。

6.

如果你没有关闭


DbDataReader


,可能会导致随机的、很难在您的代码中找到的错误,尤其是当你正在一个由


TransactionScope


上下文创建的隐式事务下操作时。

你必须始终确保您的应用程序及时关闭

DbDataReader


,无论是明确的


DbDataReader.Close


方法关闭或是逼迫


DbDataReader


释放。

7.

如果你使用


validator


特性必须引用


System.ComponentModel.DataAnnotations


程序集。

8.




FileConfigurationSource.Save


方法签名已更改。该方法有两个参数,而不是


3


个参数

9.Microsoft.Practices.EnterpriseLibrary.Configuration.Design.dll

集合的功能和其他设计时集合被一个新的集合


Microsoft.Practices.EnterpriseLibrary.Configuration.DesignTime.dll


代替。

10

,性能计数器异常从


PolicyInjection.CallHandlers


移到


PolicyInjection


程序集。

11.

包含在


Policy Injection Application Block


中的


CachingCallHandler


有未处理的安全漏洞,已经从


Policy Injection Application Block


中移除。


四、配置工具的改变:  1.

新的企业拥有一个新的


GUI


库和一个元数据驱动的可扩展性模。

2.

支持向导

3.

新的类型选择。

4.

不支持对依赖策略的


Environmental Overrides


。日志模块处理


Categories




五、缓存模块变化:  1.

缓存清除已被完全重写的性能优化

六、数据库访问模块:  1.ExecuteReader, ExecuteXmlReader, ExecuteScalar, and ExecuteNonQuery

方法具有异步版本。

2.

包含了很多新的方法和类允许你提取数据作为对象序列。例如在合适的时候使用客户端查询技术,如


LINQ.

3.

存在的方法


ExecuteReader


和新的方法


BeginExecuteReader


不接收


CommandBehavior


参数。默认的当调用这些方法的时候这些方法

会自动设置

CommandBehavior


属性到


reder


中用来关闭连接直到指定一个事务。


七、异常处理模块:  1.

日志异常处理重新使用日志模块的


Log Writer and Trace Listeners


。这在之前版本中不是默认设置。

2.

增加一个功能,通过


ExceptionManager.Process


方法接收一个默认值并返回一个值。



[EntLib]

微软企业库


5.0


学习之路


——


第二步、使用


VS2010+Data Access


模块建立多数据库项目




现在我就开始进入学习之路的第二步

——Data Access


模块,这个模块是企业库中被使用频率最高的模块,它很好的封装了数据库操作应用,为我们进行多数据库系统开发提供了便利,只需更改配置文件就可以很快的切换数据库访问(可惜还是要重写


SQL


语句,没法和


ORM


比)。


下面是我在配置企业库的时候碰到问题,如果没有碰到可以略去不看(可能有点小白)


注意:此处切换数据库配置必须是计算机中已经安装好相应的数据库访问模块,如需要进行从

MS SQL





SQLite


数据库的变更时,计算机中必须安装好


SQLite


数据库访问模块(在这里我就碰到了这个问题,原来我机器上在


VS2008


开发时已经安装过


SQLite


数据库访问模块,但是新装了


VS2010


,在


VS2010


引用对话框中也能访问到在


VS2008


安装的


SQLite


(但是在企业库


5.0


配置器中无法查看到


SQLite),


但是发现更改企业库的配置文件后无法访问


SQLite


数据库,尝试了很多方法都没用,结果死马当活马医又重新装了一遍


SQLite


数据库访问模块再重新打开企业库配置器就可以看到


SQLite


数据库了(所以请确保在企业库编辑器中可以查看到要切换的数据库,否则可能导致无法访问数据库)。看下图:


回归正题,这次的学习由于

VS2010


发布了,而且企业库


5.0


也都支持


.NET4.0


,所以决定企业库的学习之路采用


VS2010


进行学习(顺便熟悉下


.NET4


的特性,毕竟公司的项目不可能立马转移到


.NET4.0


的,现在就当练手吧)


好了,现在就开始进行第

2


步的学习了


,


首先看下项目的结构


:


项目采用仿

MS PetShop


架构,如不了解此架构可以到此查看了解:


PetShop

的系统架构设计



其中

DAL





DALSQLite


层对应


MS SQL





SQLite


数据库,


Helper


为整个项目的帮助器


现在来具体了解下

DAL







DAL


层中引用了


Helper,IDAL,EnterpriseLibrary.Common





EnterpriseLibrary.Data





4


个项目


,


其中


Helper


项目中有个


DBHelper.cs,


用于获取当前的数据对象


,


其代码如下

(采用了

C#4.0


的语法特性,默认参数,数据库对象名默认为空,这样则会调用企业库默认的数据库对象,同时也可以在调用的时候赋值,这样则根据传递过来的数据库对象名来创建数据库,通过这个参数我们将原来需要重载的


2


个方法才能实现合并成了一个方法)


:



view source


print


?


01


using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;


02


using Microsoft.Practices.EnterpriseLibrary.Data;


03


04


namespace EntLibStudy.Helper


05


{


06


public static class DBHelper


07


{


08


/// <summary>


09


/// 获取数据库对象


10


/// </summary>


11


/// <param name=”name”>数据库实例名(默认name为空,调用默认数据库实例)</param>


12


/// <returns>数据库对象</returns>


13


public static Database CreateDataBase(string name = “”)


14


{


15


//return DatabaseFactory.CreateDatabase(name);


16


return EnterpriseLibraryContainer.Current.GetInstance<Database>(name);


17


}


18


}


19


}




DAL


层中则引用


Helper


来获取数据库对象,进行数据库操作,我们现在来看下具体的数据库访问类编写代码,学员操作类


:



view source


print


?


001


using System;


002


using System.Collections.Generic;


003


using System.Data;


004


using System.Data.Common;


005


using System.Linq;


006


using System.Text;


007


008


using Microsoft.Practices.EnterpriseLibrary.Data;


009


010


using EntLibStudy.Model;


011


using EntLibStudy.Helper;


012


013


namespace EntLibStudy.DAL


014


{


015


public class StudentService : EntLibStudy.IDAL.IStudentService


016


{


017


/// <summary>


018


/// 新增学生


019


/// </summary>


020


/// <param name=”student”>学生对象</param>


021


/// <returns></returns>


022


public int Add(Student student)


023


{


024


Database db = DBHelper.CreateDataBase();


025


StringBuilder sb = new StringBuilder();


026


sb.Append(“insert into Student values(@ClassId,@SID,@Password,@Name,@Sex,@Birthday,@IsAdmin);SELECT @@IDENTITY;”);


027


DbCommand cmd = db.GetSqlStringCommand(sb.ToString());


028


db.AddInParameter(cmd, “@ClassId”, DbType.String, student.ClassId);


029


db.AddInParameter(cmd, “@SID”, DbType.String, student.Sid);


030


db.AddInParameter(cmd, “@Password”, DbType.String, student.Password);


031


db.AddInParameter(cmd, “@Name”, DbType.String, student.Name);


032


db.AddInParameter(cmd, “@Sex”, DbType.Int32, student.Sex);


033


db.AddInParameter(cmd, “@Birthday”, DbType.DateTime, student.Birthday);


034


db.AddInParameter(cmd, “@IsAdmin”, DbType.Int32, student.IsAdmin);


035


int id = Convert.ToInt32(db.ExecuteScalar(cmd));


036


return id;


037


}


038


039


/// <summary>


040


/// 更新


041


/// </summary>


042


/// <param name=”classInfo”>学生对象</param>


043


/// <returns>是否成功</returns>


044


public bool Update(Student student)


045


{


046


Database db = DBHelper.CreateDataBase();


047


StringBuilder sb = new StringBuilder();


048


sb.Append(“update Student set ClassId=@ClassId,”);


049


sb.Append(“SID=@SID,”);


050


sb.Append(“Password=@Password,”);


051


sb.Append(“Name=@Name,”);


052


sb.Append(“Sex=@Sex,”);


053


sb.Append(“Birthday=@Birthday,”);


054


sb.Append(“IsAdmin=@IsAdmin “);


055


sb.Append(” where ID=@ID”);


056


DbCommand cmd = db.GetSqlStringCommand(sb.ToString());


057


db.AddInParameter(cmd, “@ClassId”, DbType.String, student.ClassId);


058


db.AddInParameter(cmd, “@SID”, DbType.String, student.Sid);


059


db.AddInParameter(cmd, “@Password”, DbType.String, student.Password);


060


db.AddInParameter(cmd, “@Name”, DbType.String, student.Name);


061


db.AddInParameter(cmd, “@Sex”, DbType.Int32, student.Sex);


062


db.AddInParameter(cmd, “@Birthday”, DbType.DateTime, student.Birthday);


063


db.AddInParameter(cmd, “@IsAdmin”, DbType.Int32, student.IsAdmin);


064


db.AddInParameter(cmd, “@ID”, DbType.Int32, student.Id);


065


return db.ExecuteNonQuery(cmd) > 0 ? true : false;


066


}


067


068


/// <summary>


069


/// 删除


070


/// </summary>


071


/// <param name=”id”>学生ID</param>


072


/// <returns>是否成功</returns>


073


public bool Delete(int id)


074


{


075


Database db = DBHelper.CreateDataBase();


076


StringBuilder sb = new StringBuilder();


077


sb.Append(“delete from Student “);


078


sb.Append(” where ID=@ID”);


079


DbCommand cmd = db.GetSqlStringCommand(sb.ToString());


080


db.AddInParameter(cmd, “@ID”, DbType.Int32, id);


081


082


return db.ExecuteNonQuery(cmd) > 0 ? true : false;


083


}


084


085


/// <summary>


086


/// 根据学生ID查询学生对象


087


/// </summary>


088


/// <param name=”id”>学生ID</param>


089


/// <returns></returns>


090


public Student SelectById(int id)


091


{


092


Student student = null;


093


Database db = DBHelper.CreateDataBase();


094


StringBuilder sb = new StringBuilder();


095


sb.Append(“select * from Student “);


096


sb.Append(” where ID=@ID”);


097


DbCommand cmd = db.GetSqlStringCommand(sb.ToString());


098


db.AddInParameter(cmd, “@ID”, DbType.Int32, id);


099


100


using (IDataReader reader = db.ExecuteReader(cmd))


101


{


102


if (reader.Read())


103


{


104


student = new Student()


105


{


106


Id = reader.GetInt32(0),


107


ClassId = reader.GetInt32(1),


108


Sid = reader.GetString(2),


109


Password = reader.GetString(3),


110


Name = reader.GetString(4),


111


Sex = reader.GetInt32(5),


112


Birthday = reader.GetDateTime(6),


113


IsAdmin = reader.GetInt32(7)


114


};


115


}


116


}


117


118


return student;


119


}


120


121


/// <summary>


122


/// 查询所有学生信息


123


/// </summary>


124


/// <returns></returns>


125


public IList<Student> SelectAll()


126


{


127


List<Student> list = new List<Student>();


128


Database db = DBHelper.CreateDataBase();


129


StringBuilder sb = new StringBuilder();


130


sb.Append(“select * from Student “);


131


DbCommand cmd = db.GetSqlStringCommand(sb.ToString());


132


133


using (IDataReader reader = db.ExecuteReader(cmd))


134


{


135


while (reader.Read())


136


{


137


list.Add(new Student()


138


{


139


Id = reader.GetInt32(0),


140


ClassId = reader.GetInt32(1),


141


Sid = reader.GetString(2),


142


Password = reader.GetString(3),


143


Name = reader.GetString(4),


144


Sex = reader.GetInt32(5),


145


Birthday = reader.GetDateTime(6),


146


IsAdmin = reader.GetInt32(7)


147


});


148


}


149


}


150


return list;


151


}


152


153


/// <summary>


154


/// 查询所有学生信息


155


/// </summary>


156


/// <returns></returns>


157


public IList<Student> SelectAllMapper()


158


{


159


var list = new List<Student>();


160


Database db = DBHelper.CreateDataBase();


161


DataAccessor<Student> studentAccessor;


162


//studentAccessor = db.CreateSqlStringAccessor(“select * from Student”,


163


// MapBuilder<Student>.MapAllProperties().


164


// Build()


165


// );


166


studentAccessor = db.CreateSqlStringAccessor(“select * from Student”,


167


MapBuilder<Student>.MapAllProperties().


168


Map(p => p.Id).ToColumn(“ID”).


169


Map(p => p.Sid).ToColumn(“SID”).


170


Map(p => p.Password).WithFunc(f => “******”).//将密码转换为”*”,无法直接查看


171


Map(p => p.Name).WithFunc(ToUpperName).//将学员名称转换为大写


172


Map(p => p.Sex).ToColumn(“Sex”).


173


Map(p => p.Birthday).ToColumn(“Birthday”).


174


Build()


175


);


176


list = studentAccessor.Execute().ToList();


177


return list;


178


}


179


180


/// <summary>


181


/// 将学员名称转换为大写


182


/// </summary>


183


/// <param name=”dataRecord”></param>


184


/// <returns></returns>


185


private string ToUpperName(IDataRecord dataRecord)


186


{


187


var name = (string)dataRecord[“Name”];


188


return name.ToUpper();


189


}


190


191


public Student SelectBySid(string sid)


192


{


193


Student student = null;


194


Database db = DBHelper.CreateDataBase();


195


StringBuilder sb = new StringBuilder();


196


sb.Append(“select * from Student “);


197


sb.Append(” where SID=@SID”);


198


DbCommand cmd = db.GetSqlStringCommand(sb.ToString());


199


db.AddInParameter(cmd, “@SID”, DbType.String, sid);


200


201


using (IDataReader reader = db.ExecuteReader(cmd))


202


{


203


if (reader.Read())


204


{


205


student = new Student()


206


{


207


Id = reader.GetInt32(0),


208


ClassId = reader.GetInt32(1),


209


Sid = reader.GetString(2),


210


Password = reader.GetString(3),


211


Name = reader.GetString(4),


212


Sex = reader.GetInt32(5),


213


Birthday = reader.GetDateTime(6),


214


IsAdmin = reader.GetInt32(7)


215


};


216


}


217


}


218


219


return student;


220


}


221


222


}


223


}


其中的代码都是采用了比较常见的老套路

:


1

、获取数据库对象


2

、构建


Command


对象并进行执行语句及参数赋值


3

、通过数据库对象调用相应方法执行


Command


企业库在

Data Access


上帮我们做了比较好的封装,相当于为我们提供了如


SQLHelper,OracleHelper





,


只不过这个帮助类转换了一个个数据库的对象


,


通过数据库对象来对数据库数据进行操作


(个人认为通过这种方式进行操作更加直观,而且企业库的对

SQL


语句的参数操作方法也很直观:


AddInParameter





AddOutParameter





GetParameterValue


很好的区分了参数的操作,比原来的


SQLCommand


好多了)


如果仔细看了上面操作代码的朋友肯定发现了类中有个叫

SelectAllMapper


的方法,

这个方法采用的是企业库

5.0


中新提供的


Accessor


进行


RowMapper


来直接为实体赋值,相比原来的使用


reader


方式取值赋值更加优雅

,只要

SQL


查询出来的对象字段和实体对象属性一样就可以使用


MapAllProperties()


方法直接赋值


,


如果不同的话可以使用


map


方法来对个别属性单独映射,而且在映射的时候还可以使用


WithFunc


来进行进一步操作,在代码中我将密码进行了替换,以


“*”


的形式展示,同时把学员的名称以大写的形式展示。


(注:更多的企业库

Data Access


模块方法使用可以点击


这里

下载微软给出的学习例子和

http://www.entlib.com/

发布的学习手册

)


在完成底层的操作,现在我们就开始对企业库的数据库访问进行配置:




Web


层的


Web.config


上右键打开企业库配置器:


Blocks-Add Data Settings-Add DataBase Connstring,


新建


2


个数据库对象,一个是


MS SqlServer


数据库


,


一个是


SQLite


数据库


.


新建一个数据库设置


新建二个数据库连接


一个为

EntLibStudy


,另一个为


EntLibSQLite


我们来看下具体的配置文件代码:



view source


print


?


01


<configuration>


02


<configSections>


03


<section name=”dataConfiguration” type=”Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ requirePermission=”true” />


04


</configSections>


05


06


<dataConfiguration defaultDatabase=”EntLibStudy” />


07


<connectionStrings>


08


<add name=”EntLibStudy” connectionString=”server=VOLK\SQL2005;database=EntLibStudy;Integrated Security=True;”


09


providerName=”System.Data.SqlClient” />


10


<add name=”EntLibStudySQLite” connectionString=”data source=|DataDirectory|EntLibStudySQLite.db3″


11


providerName=”System.Data.SQLite” />


12


</connectionStrings>


13


14


<appSettings>


15


<add key=”DAL” value=”EntLibStudy.DAL” />


16


</appSettings>


17


18


<system.web>


19


<compilation debug=”true” targetFramework=”4.0″ >


20


<expressionBuilders>


21


<add expressionPrefix=”RouteUrl” type=”System.Web.Compilation.RouteUrlExpressionBuilder”/>


22


<add expressionPrefix=”RouteValue” type=”System.Web.Compilation.RouteValueExpressionBuilder”/>


23


</expressionBuilders>


24


</compilation>


25


<authentication mode=”Forms”>


26


</authentication>


27


28


</system.web>


29


30


</configuration>


至此我们就完成了

Data Access


模块的代码编写和基本设置(具体代码请到文章底部下载源代码,类似代码则不再描述)。


这时如果项目需求发生了变更

,


由于成本太高不能使用


MS SQL SERVER


,而要改用


SQLite


数据库时则只需更改配置文件,将

dataConfiguration配置节中defaultDatabase更改为EntLibStudySQLite,将appSettings配置节中DAL的值改为EntLibStudy.DALSQLite即可立刻切换到

SQLite


数据库。


下面我来看下运行出来的效果:


红色框中地址采用了

ASP.NET4


中的路由功能


,


实现了地址重写


红框中如上面的分析

,





DAL


层进行属性映射的时候已经将密码以


*


代替,学员姓名以大写形式展现(此页面仅用来展示属性映射,无其他用处,页面地址为:


~/Student/StudentList.aspx)


至此,学习之路的第二步

——Data Access


模块的学习就到此为止了,其他一些东西请下载源代码查看。


注意:


1




MSSQL


数据库在


DataBase


目录下(需要自行附加数据库),


SQLite


数据库在


Web


目录的


App_Data


下,由于考虑到项目的大小,所以每个项目的


BIN


目录都已经删除,如出现无法生成项目请自行添加相关企业库的


DLL





2

、由于微软企业库


5.0


学习之路这个系列我是准备以一个小型项目的形式介绍企业库的各模块,所以源代码会根据系列文章的更新而更新,所以源代码不能保证与文章中所贴代码相同。


3

、项目开发环境为:


VS2010+SQL2005




转载于:https://www.cnblogs.com/iChina/archive/2011/11/05/2237481.html