进来公司需要接入一套用户权限系统(原先的后台登录系统,用户是在xml文件里面写死的,包括访问权限,用户名密码等)。由于时间有限,又不想让自己的代码跟原先的代码一样紊乱。经过综合考虑,这里就放弃了Hibernate和Spring(配置过于繁琐,hql写起来也颇为麻烦),于是乎选择了IBatis和Autofac。
优点:IBatis和Autofac都是轻量级框架,相对于Hibernate和Spring配置相对简单一些,效率上也优于后者。
IBatis程序集:IBatisNet.Common.dll,IBatisNet.DataMapper.dll
IBatis配置文件:SQLMap.config,providers.config
- SQLMap.config
<?xml version="1.0" encoding="utf-8"?>
<sqlMapConfig
xmlns="http://ibatis.apache.org/dataMapper"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<settings>
<!--/是否使用Satement命名空间,这里的命名空间指的是映射文件中sqlMap节点的namespace属性,默认是false-->
<setting useStatementNamespaces="false"/>
<!--是否启用DataMapper的缓存机制,针对全部的SqlMap,默认是true-->
<setting cacheModelsEnabled="true"/>
<!--是否启用SqlMapConfig.xsd schema验证映射文件,默认是false-->
<setting validateSqlMap="false"/>
</settings>
<!--配置数据驱动提供类配置文件的路径和文件名-->
<providers resource="Config/providers.config"/>
<!--如果在providers.config文件中指定了默认的数据库驱动,那么provider节点就不需要设置了,它的作用是在换数据库驱动时不需要修改providers.config文件。datasource节点用于指定ADO.NET Connection String.-->
<database>
<provider name="sqlServer2.0"/>
<dataSource name="mydb" connectionString="data source=127.0.0.1;database=UserRole;user id=sa;password=sa;"/>
</database>
<!--指定映射的文件的位置-->
<sqlMaps>
<sqlMap resource="Maps/PageActionMap.xml"/>
<sqlMap resource="Maps/PageMap.xml"/>
<sqlMap resource="Maps/PermissionPageActionMap.xml"/>
<sqlMap resource="Maps/PermissionPageMap.xml"/>
<sqlMap resource="Maps/RoleMap.xml"/>
<sqlMap resource="Maps/UserMap.xml"/>
<sqlMap resource="Maps/UserRoleMap.xml"/>
</sqlMaps>
</sqlMapConfig>
上述映射文件的UserMap.xml
<?xml version="1.0" encoding="utf-8" ?>
<!--namespace必须用否者就报错(读取配置文件报:未将对象引用设置到对象的实例)-->
<sqlMap namespace="User" xmlns="http://ibatis.apache.org/mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<alias>
<!-- alias:取别名
assembly:表示类所在的文件
type:表示该类的完整的名称
-->
<typeAlias alias="User" assembly="HC.JiShi.UserRole.dll" type="HC.JiShi.UserRole.Entity.UserPo" />
<typeAlias alias="UserPermissionPage" assembly="HC.JiShi.UserRole.dll" type="HC.JiShi.UserRole.Entity.UserPermissionPagePo" />
<typeAlias alias="UserPermissionPageAction" assembly="HC.JiShi.UserRole.dll" type="HC.JiShi.UserRole.Entity.UserPermissionPageActionPo" />
</alias>
<resultMaps>
<resultMap id="UserResult" class="User">
<!--如果不取别名要使用类的全路径‘HC.JiShi.UserRole.Entity.UserPo’-->
<result property="Id" column="Id"/>
<result property="UserName" column="UserName"/>
<result property="Password" column="Password"/>
<result property="CreateDate" column="CreateDate"/>
<result property="IsAdmin" column="IsAdmin"/>
<result property="IsValid" column="IsValid"/>
</resultMap>
<resultMap id="UserPermissionPageResult" class="UserPermissionPage">
<result property="UserId" column="UserId"/>
<result property="PageId" column="PageId"/>
<result property="PageName" column="PageName"/>
<result property="Url" column="Url"/>
<result property="Domain" column="Domain"/>
</resultMap>
<resultMap id="UserPermissionPageActionResult" class="UserPermissionPageAction">
<result property="UserId" column="UserId"/>
<result property="PageActionId" column="PageActionId"/>
<result property="PageId" column="PageId"/>
<result property="ActionName" column="ActionName"/>
<result property="ActionUrl" column="ActionUrl"/>
</resultMap>
</resultMaps>
<statements>
<select id="GetUserById" parameterClass="int" resultClass="User">
SELECT * FROM [User] WHERE Id=#Id#
</select>
<insert id="AddUser" parameterClass="User">
INSERT INTO [User] VALUES(#UserName#,#Password#,#IsAdmin#,#IsValid#,#CreateDate#)
<selectKey resultClass="int" type="post" property="Id">
SELECT @@IDENTITY
</selectKey>
</insert>
<delete id="DeleteUser" parameterClass="int" restultClass="int">
DELETE FROM [User] WHERE Id=#Id#
</delete>
<delete id="DeleteUsers" parameterClass="List">
DELETE FROM [User]
<iterate prepend="WHERE" open="(" close=")" conjunction="OR">
Id = #[]#
</iterate>
</delete>
<update id="UpdateUser" parameterClass="User" restltClass="int">
UPDATE [User] SET UserName=#UserName#,Password=#Password#,IsAdmin=#IsAdmin#,IsValid=#IsValid#,CreateDate=#CreateDate# WHERE Id=#Id#
</update>
</statements>
</sqlMap>
IBatis操作sql说明
属性 | 说明 |
parameterMap | 参数映射,需结合parameterMap节点对映射关系加以定义,对于存储过程之外的statement而言,建议使用parameterClass作为参数配置方式,一方面避免了参数映射配置工作,另一方面其性能表现更加出色 |
parameterClass | 参数类。指定了参数类型的完整类名(包括命名空间),可以通过别名避免每次书写冗长的类名 |
resultMap | 结果映射,需结合resultMap节点对映射关系加以定义 |
resultClass | 结果类。指定了结果类型的完整类名(包括命名空间),可以通过别名避免每次书写冗长的类名 |
cacheModel | Statement对应的Cache模块 |
extends | 重复使用SQL子句 |
上面的底层已经写完,当然还需要一个IBatis的操作类Mapper.cs,这是我网上找的,有兴趣的可以自己再封装完善一下。
Mapper.cs
public class Mapper
{
private static volatile ISqlMapper _mapper = null;
protected static void Configure(object obj)
{
_mapper = null;
}
protected static void InitMapper()
{
var handler = new ConfigureHandler(Configure);
var builder = new DomSqlMapBuilder();
_mapper = builder.ConfigureAndWatch(handler);
}
public static ISqlMapper Instance()
{
if (_mapper == null)
{
lock (typeof(SqlMapper))
{
if (_mapper == null) // double-check
{
InitMapper();
}
}
}
return _mapper;
}
public static ISqlMapper Get()
{
return Instance();
}
/// <summary>
/// RealMarket Mapper
/// </summary>
public static ISqlMapper GetMaper
{
get
{
if (_mapper == null)
{
lock (typeof(ISqlMapper))
{
if (_mapper == null)
{
var hander = new ConfigureHandler(Configure);
var builder = new DomSqlMapBuilder();
_mapper = builder.ConfigureAndWatch("config/sqlmap.config", hander);
}
}
}
return _mapper;
}
}
}
User表的操作类UserDao.cs
public class UserDao : IUserDao
{
public int AddUser(UserPo user)
{
Object obj = Mapper.GetMaper.Insert("AddUser", user);
return (int)obj;
}
public void DeleteUser(int id)
{
Mapper.GetMaper.Delete("DeleteUser", id);
}
public void DeleteUsers(List<int> ids)
{
Mapper.GetMaper.Delete("DeleteUsers", ids);
}
public void UpdateUser(UserPo user)
{
Mapper.GetMaper.Update("UpdateUser", user);
}
public void UpdateUserName(int id, string userName)
{
var htPram = new Hashtable { { "Id", id }, { "UserName", userName } };
Mapper.GetMaper.Update("UpdateUserName", htPram);
}
public void UpdatePassword(int id, string password)
{
var htPram = new Hashtable { { "Id", id }, { "Password", password } };
Mapper.GetMaper.Update("UpdatePassword", htPram);
}
public UserPo GetUser(int id)
{
return Mapper.GetMaper.QueryForObject<UserPo>("GetUserById", id);
}
}
上面是IBatis的部署及使用步骤,其中UserDao用户操作类继承自IUserDao
public interface IUserDao
{
/// <summary>
/// 添加
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
int AddUser(UserPo user);
/// <summary>
/// 删除
/// </summary>
/// <param name="id"></param>
void DeleteUser(int id);
/// <summary>
/// 批量删除
/// </summary>
/// <param name="ids"></param>
void DeleteUsers(List<int> ids);
/// <summary>
/// 更新
/// </summary>
/// <param name="user"></param>
void UpdateUser(UserPo user);
/// <summary>
/// 更新用户名
/// </summary>
/// <param name="id"></param>
/// <param name="userName"></param>
void UpdateUserName(int id, string userName);
/// <summary>
/// 更新密码
/// </summary>
/// <param name="id"></param>
/// <param name="password"></param>
void UpdatePassword(int id, string password);
/// <summary>
/// 获取用户
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
UserPo GetUser(int id);
}
那么如何使用Autofac来调用IUserDao呢?这里我们只需要通过代码在容器里面注册用户操作类
Container.cs
using Autofac;
public class Container
{
public static IContainer CommonContainer { get; set; }
private static readonly ContainerBuilder Builder = new ContainerBuilder();
static Container()
{
RegisterUserDao();
CommonContainer = Builder.Build();
}
private static void RegisterUserDao()
{
Builder.RegisterType<UserDao>().As<IUserDao>();
}
}
最后一步使用
public class UserService : IUserService
{
private readonly IUserDao _userDao = Container.CommonContainer.Resolve<IUserDao>();
public int AddUser(User user)
{
var checkUser = _userDao.GetUser(user.UserName);
//判断用户名是否存在
if (!checkUser.IsNullOrEmpty())
{
throw new BussinessException(ERROR_USERNAME_EXIST);
}
user.Password = DEncrypt.Encrypt(user.Password, Key);
Object obj = _userDao.AddUser(GetUserPoFromUser(user));
return (int)obj;
}
public void DeleteUser(int id)
{
_userDao.DeleteUser(id);
}
public void DeleteUsers(List<int> ids)
{
_userDao.DeleteUsers(ids);
}
}
可以按照上述操作扩展业务,完善业务层和数据层。