微软企业库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个方法才能实现合并成了一个方法)
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Data; namespace EntLibStudy.Helper
{
public static class DBHelper
{
/// <summary>
/// 获取数据库对象
/// </summary>
/// <param name="name">数据库实例名(默认name为空,调用默认数据库实例)</param>
/// <returns>数据库对象</returns>
public static Database CreateDataBase(string name = "")
{
//return DatabaseFactory.CreateDatabase(name);
return EnterpriseLibraryContainer.Current.GetInstance<Database>(name);
}
}
}
在DAL层中则引用Helper来获取数据库对象,进行数据库操作,我们现在来看下具体的数据库访问类编写代码,学员操作类:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Text; using Microsoft.Practices.EnterpriseLibrary.Data; using EntLibStudy.Model;
using EntLibStudy.Helper; namespace EntLibStudy.DAL
{
public class StudentService : EntLibStudy.IDAL.IStudentService
{
/// <summary>
/// 新增学生
/// </summary>
/// <param name="student">学生对象</param>
/// <returns></returns>
public int Add(Student student)
{
Database db = DBHelper.CreateDataBase();
StringBuilder sb = new StringBuilder();
sb.Append("insert into Student values(@ClassId,@SID,@Password,@Name,@Sex,@Birthday,@IsAdmin);SELECT @@IDENTITY;");
DbCommand cmd = db.GetSqlStringCommand(sb.ToString());
db.AddInParameter(cmd, "@ClassId", DbType.String, student.ClassId);
db.AddInParameter(cmd, "@SID", DbType.String, student.Sid);
db.AddInParameter(cmd, "@Password", DbType.String, student.Password);
db.AddInParameter(cmd, "@Name", DbType.String, student.Name);
db.AddInParameter(cmd, "@Sex", DbType.Int32, student.Sex);
db.AddInParameter(cmd, "@Birthday", DbType.DateTime, student.Birthday);
db.AddInParameter(cmd, "@IsAdmin", DbType.Int32, student.IsAdmin);
int id = Convert.ToInt32(db.ExecuteScalar(cmd));
return id;
} /// <summary>
/// 更新
/// </summary>
/// <param name="classInfo">学生对象</param>
/// <returns>是否成功</returns>
public bool Update(Student student)
{
Database db = DBHelper.CreateDataBase();
StringBuilder sb = new StringBuilder();
sb.Append("update Student set ClassId=@ClassId,");
sb.Append("SID=@SID,");
sb.Append("Password=@Password,");
sb.Append("Name=@Name,");
sb.Append("Sex=@Sex,");
sb.Append("Birthday=@Birthday,");
sb.Append("IsAdmin=@IsAdmin ");
sb.Append(" where ID=@ID");
DbCommand cmd = db.GetSqlStringCommand(sb.ToString());
db.AddInParameter(cmd, "@ClassId", DbType.String, student.ClassId);
db.AddInParameter(cmd, "@SID", DbType.String, student.Sid);
db.AddInParameter(cmd, "@Password", DbType.String, student.Password);
db.AddInParameter(cmd, "@Name", DbType.String, student.Name);
db.AddInParameter(cmd, "@Sex", DbType.Int32, student.Sex);
db.AddInParameter(cmd, "@Birthday", DbType.DateTime, student.Birthday);
db.AddInParameter(cmd, "@IsAdmin", DbType.Int32, student.IsAdmin);
db.AddInParameter(cmd, "@ID", DbType.Int32, student.Id);
return db.ExecuteNonQuery(cmd) > ? true : false;
} /// <summary>
/// 删除
/// </summary>
/// <param name="id">学生ID</param>
/// <returns>是否成功</returns>
public bool Delete(int id)
{
Database db = DBHelper.CreateDataBase();
StringBuilder sb = new StringBuilder();
sb.Append("delete from Student ");
sb.Append(" where ID=@ID");
DbCommand cmd = db.GetSqlStringCommand(sb.ToString());
db.AddInParameter(cmd, "@ID", DbType.Int32, id); return db.ExecuteNonQuery(cmd) > ? true : false;
} /// <summary>
/// 根据学生ID查询学生对象
/// </summary>
/// <param name="id">学生ID</param>
/// <returns></returns>
public Student SelectById(int id)
{
Student student = null;
Database db = DBHelper.CreateDataBase();
StringBuilder sb = new StringBuilder();
sb.Append("select * from Student ");
sb.Append(" where ID=@ID");
DbCommand cmd = db.GetSqlStringCommand(sb.ToString());
db.AddInParameter(cmd, "@ID", DbType.Int32, id); using (IDataReader reader = db.ExecuteReader(cmd))
{
if (reader.Read())
{
student = new Student()
{
Id = reader.GetInt32(),
ClassId = reader.GetInt32(),
Sid = reader.GetString(),
Password = reader.GetString(),
Name = reader.GetString(),
Sex = reader.GetInt32(),
Birthday = reader.GetDateTime(),
IsAdmin = reader.GetInt32()
};
}
} return student;
} /// <summary>
/// 查询所有学生信息
/// </summary>
/// <returns></returns>
public IList<Student> SelectAll()
{
List<Student> list = new List<Student>();
Database db = DBHelper.CreateDataBase();
StringBuilder sb = new StringBuilder();
sb.Append("select * from Student ");
DbCommand cmd = db.GetSqlStringCommand(sb.ToString()); using (IDataReader reader = db.ExecuteReader(cmd))
{
while (reader.Read())
{
list.Add(new Student()
{
Id = reader.GetInt32(),
ClassId = reader.GetInt32(),
Sid = reader.GetString(),
Password = reader.GetString(),
Name = reader.GetString(),
Sex = reader.GetInt32(),
Birthday = reader.GetDateTime(),
IsAdmin = reader.GetInt32()
});
}
}
return list;
} /// <summary>
/// 查询所有学生信息
/// </summary>
/// <returns></returns>
public IList<Student> SelectAllMapper()
{
var list = new List<Student>();
Database db = DBHelper.CreateDataBase();
DataAccessor<Student> studentAccessor;
//studentAccessor = db.CreateSqlStringAccessor("select * from Student",
// MapBuilder<Student>.MapAllProperties().
// Build()
// );
studentAccessor = db.CreateSqlStringAccessor("select * from Student",
MapBuilder<Student>.MapAllProperties().
Map(p => p.Id).ToColumn("ID").
Map(p => p.Sid).ToColumn("SID").
Map(p => p.Password).WithFunc(f => "******").//将密码转换为"*",无法直接查看
Map(p => p.Name).WithFunc(ToUpperName).//将学员名称转换为大写
Map(p => p.Sex).ToColumn("Sex").
Map(p => p.Birthday).ToColumn("Birthday").
Build()
);
list = studentAccessor.Execute().ToList();
return list;
} /// <summary>
/// 将学员名称转换为大写
/// </summary>
/// <param name="dataRecord"></param>
/// <returns></returns>
private string ToUpperName(IDataRecord dataRecord)
{
var name = (string)dataRecord["Name"];
return name.ToUpper();
} public Student SelectBySid(string sid)
{
Student student = null;
Database db = DBHelper.CreateDataBase();
StringBuilder sb = new StringBuilder();
sb.Append("select * from Student ");
sb.Append(" where SID=@SID");
DbCommand cmd = db.GetSqlStringCommand(sb.ToString());
db.AddInParameter(cmd, "@SID", DbType.String, sid); using (IDataReader reader = db.ExecuteReader(cmd))
{
if (reader.Read())
{
student = new Student()
{
Id = reader.GetInt32(),
ClassId = reader.GetInt32(),
Sid = reader.GetString(),
Password = reader.GetString(),
Name = reader.GetString(),
Sex = reader.GetInt32(),
Birthday = reader.GetDateTime(),
IsAdmin = reader.GetInt32()
};
}
} return student;
} }
}
其中的代码都是采用了比较常见的老套路:
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
我们来看下具体的配置文件代码:
<configuration>
<configSections>
<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" />
</configSections> <dataConfiguration defaultDatabase="EntLibStudy" />
<connectionStrings>
<add name="EntLibStudy" connectionString="server=VOLK\SQL2005;database=EntLibStudy;Integrated Security=True;"
providerName="System.Data.SqlClient" />
<add name="EntLibStudySQLite" connectionString="data source=|DataDirectory|EntLibStudySQLite.db3"
providerName="System.Data.SQLite" />
</connectionStrings> <appSettings>
<add key="DAL" value="EntLibStudy.DAL" />
</appSettings> <system.web>
<compilation debug="true" targetFramework="4.0" >
<expressionBuilders>
<add expressionPrefix="RouteUrl" type="System.Web.Compilation.RouteUrlExpressionBuilder"/>
<add expressionPrefix="RouteValue" type="System.Web.Compilation.RouteValueExpressionBuilder"/>
</expressionBuilders>
</compilation>
<authentication mode="Forms">
</authentication> </system.web> </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。
4、管理员帐户:admin
密码:admin
项目下载地址:点我下载
微软企业库5.0 学习之路——第二步、使用VS2010+Data Access模块建立多数据库项目的更多相关文章
- 微软企业库5.0 学习之路——第九步、使用PolicyInjection模块进行AOP—PART4——建立自定义Call Handler实现用户操作日志记录
在前面的Part3中, 我介绍Policy Injection模块中内置的Call Handler的使用方法,今天则继续介绍Call Handler——Custom Call Handler,通过建立 ...
- [EntLib]微软企业库5.0 学习之路——第一步、基本入门
话说在大学的时候帮老师做项目的时候就已经接触过企业库了但是当初一直没明白为什么要用这个,只觉得好麻烦啊,竟然有那么多的乱七八糟的配置(原来我不知道有配置工具可以进行配置,请原谅我的小白). 直到去年在 ...
- 微软企业库5.0 学习之路——第八步、使用Configuration Setting模块等多种方式分类管理企业库配置信息
在介绍完企业库几个常用模块后,我今天要对企业库的配置文件进行处理,缘由是我打开web.config想进行一些配置的时候发现web.config已经变的异常的臃肿(大量的企业库配置信息充斥其中),所以决 ...
- 微软企业库5.0 学习之路——第七步、Cryptographer加密模块简单分析、自定义加密接口及使用—下篇
在上一篇文章中, 我介绍了企业库Cryptographer模块的一些重要类,同时介绍了企业库Cryptographer模块为我们提供的扩展接口,今天我就要根据这些 接口来进行扩展开发,实现2个加密解密 ...
- 微软企业库5.0 学习之路——第六步、使用Validation模块进行服务器端数据验证
前端时间花了1个多星期的时间写了使用jQuery.Validate进行客户端验证,但是那仅仅是客户端的验证,在开发项目的过程中,客户端的信息永远是不可信的,所以我们还需要在服务器端进行服务器端的验证已 ...
- 微软企业库5.0 学习之路——第四步、使用缓存提高网站的性能(EntLib Caching)
首先先补习下企业库的Caching Application Block的相关知识: 1.四大缓存方式,在Caching Application Block中,主要提供以下四种保存缓存数据的途径,分别是 ...
- 微软企业库5.0 学习之路——第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——下篇
一.独立验证器 我上篇中我将AndCompositeValidator和OrCompositeValidator归为独立验证器,这2个验证器主要是为了第一类验证服务,可以进行多种验证组合在一起进行复杂 ...
- 微软企业库5.0 学习之路——扩展学习篇、库中的依赖关系注入(重构 Microsoft Enterprise Library)[转]
这篇文章是我在patterns & practices看到的一篇有关EntLib5.0的文章,主要介绍了EntLib5.0的这次的架构变化由来,觉得很不错,大家可以看一下! 在过去几年中,依赖 ...
- 微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(3)
今天继续介绍Unity,在上一篇的文章中,我介绍了使用UnityContainer来注册对象之间的关系.注册已存在的对象之间的关系,同时着重介绍 了Unity内置的各种生命周期管理器的使用方法,今天则 ...
随机推荐
- python2.6升级2.7导致yum无法使用 No module named yum
这里有解决方法:https://teddysun.com/473.html 记住旧版本 Python 2.6.6 的重要路径如下所示,在运行 yum 命令的时候,会提示你哪个 module 不存在,不 ...
- FreeRTOS 问题归纳
分配给FreeRTOS的heap过少,可能出现任务创建不成功:也可能调用vTaskStartScheduler()后有返回(也就是执行下一条程序),实质上也是vTaskStartScheduler() ...
- C语言实现单链表的遍历,逆序,插入,删除
单链表的遍历,逆序,插入,删除 #include<stdio.h> #include<stdlib.h> #include <string.h> #define b ...
- 字符串类dp的题目总结
熟练掌握回文串吧,大致有dp或者模拟类的吧 ①dp+预处理,懂得如何枚举回文串(一) ②dp匹配类型的题目(二) ③dp+预处理 子串类型 (三) ④字符串的组合数(四) 一:划分成回文串 UVA11 ...
- Linux局域网内文件传送
先安装ssh服务 sudo apt-get install ssh 普通传输文件,可以使用scp命令 1.将本地文件复制到目标机器: scp 文件名 用户名@目标机器IP:目标机器路径 回车后输入密 ...
- Linux下Tomcat重启脚本
我们重启Tomcat服务的时候,Tomcat自带的shutdown.sh脚本有时并不能真正杀死进程,经常需要我们用“kill -9 pid”的方式来杀死进程. 下面的脚本可以简化我们的操作,执行可杀死 ...
- C语言数据结构-栈
一.栈的定义 栈(statck)这种数据结构在计算机中是相当出名的.栈中的数据是先进后出的(First In Last Out, FILO).栈只有一个出口,允许新增元素(只能在栈顶上增加). 移出元 ...
- 我要AFO啦好伤感啊
我要AFO啦 虽然一直很垃圾 但是也很开心 接下来我要去学物理啦 原因是今天早上没有吃早餐?! 就这样把~ 白白
- 省队集训Day1 总统选举
[题目大意] 一个$n$个数的序列,$m$次操作,每次选择一段区间$[l, r]$,求出$[l, r]$中出现超过一半的数. 如果没有超过一半的数,那么就把答案钦定为$s$,每次会有$k$个数进行改变 ...
- 【HDU】5269 ZYB loves Xor I
[算法]trie [题解] 为了让数据有序,求lowbit无法直接排序,从而考虑倒过来排序,然后数据就会呈现出明显的规律: 法一:将数字倒着贴在字典树上,则容易发现两数的lowbit就是它们岔道结点的 ...