最近没啥事,研究了一下web api的框架, 选型用的是dapper+autofac+mysql, 简单的三层架构,总体框架如下,刚开始没有设计的太复杂:
APIDapperTool里面是封装的dapper的一些dapper的操作,以及对多数据库的支持,dapper是一个轻量级的orm工具,与其说是一个orm,还不如称呼为dbhelper。它是一个对数据库操作的封装,不需要装什么其他的组件,只需要在nuget里面安装dapper,一个单文件就能实现操作,对其他数据库的支持也非常好,数据库间的切换也非常方便:
DbConnectionFactory这个里面是对dapper连接的的封装,以及多数据库的支持,切换,代码如下:
public class DbConnectionFactory
{
/// 接收数据库类型,如:Oracle,MySQL,SqlServer。目前只支持者三种类型数据库的切换
private static string _dbType = string.Empty;
/// 数据库连接名
private static string _connection = string.Empty;
/// 获取连接名
private static string Connection
{
get { return _connection; }
//set { _connection = value; }
}
/// 返回连接实例
private static IDbConnection dbConnection = null;
#region 这种方式初始化属性值时,出现延迟的情况,导致静态方法被调用时,属性值为空,异常报错,因此弃用该方式,采用单例模式
//{
// get
// {
// string dbConnection = ConfigurationManager.AppSettings["DbConnection"].ToString();
// if (!string.IsNullOrEmpty(dbConnection) && dbConnection.Contains('_'))
// {
// //获取:数据库类型_连接名:SqlServer_SqlConnection
// string[] strArray = dbConnection.Split('_');
// //接收:数据库类型
// _dbType = strArray[0].ToUpper();
// //接收:数据库连接名
// _connection = ConfigurationManager.ConnectionStrings[strArray[1]].ConnectionString;
// }
// return _connection;
// }
//}
#endregion
/// 静态变量保存类的实例
private static DbConnectionFactory uniqueInstance;
/// 定义一个标识确保线程同步
private static readonly object locker = new object();
///
/// 私有的构造方法,使外界不能创建该类的实例
///
private DbConnectionFactory()
{
string dbConnection = ConfigurationManager.AppSettings["DbConnection"].ToString();
if (!string.IsNullOrEmpty(dbConnection) && dbConnection.Contains('_'))
{
//获取:数据库类型_连接名:SqlServer_SqlConnection
string[] strArray = dbConnection.Split('_');
//接收:数据库类型
_dbType = strArray[0].ToUpper();
//接收:数据库连接名
_connection = ConfigurationManager.ConnectionStrings[strArray[1]].ConnectionString;
}
}
///
/// 全局访问点
///
/// 返回单一实例
public static DbConnectionFactory GetInstance()
{
// 当第一个线程运行到这里时,此时会对locker对象 "加锁",
// 当第二个线程运行该方法时,首先检测到locker对象为"加锁"状态,该线程就会挂起等待第一个线程解锁
// lock语句运行完之后(即线程运行完之后)会对该对象"解锁"
// 双重锁定只需要一句判断就可以了
if (uniqueInstance == null)
{
lock (locker)
{
// 如果类的实例不存在则创建,否则直接返回
if (uniqueInstance == null)
{
uniqueInstance = new DbConnectionFactory();
}
}
}
return uniqueInstance;
}
///
/// 根据 Appsetting配置中的数据库类型和连接名,打开当前配置的数据库连接。
///
///
public static IDbConnection OpenCurrentDbConnection()
{
switch (_dbType)
{
case "SQLSERVER":
if (dbConnection == null)
{
dbConnection = new SqlConnection(Connection);
}
break;
case "MYSQL":
if (dbConnection == null)
{
dbConnection = new MySqlConnection(Connection);
}
break;
default:
break;
}
//判断连接状态
if (dbConnection.State == ConnectionState.Closed)
{
dbConnection.Open();
}
return dbConnection;
}
///
/// 打开自定义配置的数据库类型和连接名
///
/// 连接内容
/// 数据库类型
///
public static IDbConnection OpenCurrentDbConnection(string dbConnectionString, DbType dbType = DbType.SqlServer)
{
switch (dbType.ToString().ToUpper())
{
case "SQLSERVER":
if (dbConnection == null)
{
dbConnection = new SqlConnection(dbConnectionString);
}
break;
case "MYSQL":
if (dbConnection == null)
{
dbConnection = new MySqlConnection(dbConnectionString);
}
break;
default:
break;
}
//判断连接状态
if (dbConnection.State == ConnectionState.Closed)
{
dbConnection.Open();
}
return dbConnection;
}
}
///
/// 数据库类型
///
public enum DbType
{
SqlServer = 1,
Oracle = 2,
MySQL = 3
}
采用的是单例模式,双锁检查,获取连接。
DbContexts: 这个里面是对一些数据库操作的封装,增删改查,集合查询等等,代码如下:
public static class DbContexts
{
/// 获取开启数据库的连接
private static IDbConnection Db
{
get
{
//创建单一实例
DbConnectionFactory.GetInstance();
return DbConnectionFactory.OpenCurrentDbConnection();
}
}
///
/// 查出一条记录
///
///
///
public static dynamic SelectFirst(string sql)
{
return Db.QueryFirst(sql);
}
///
/// 查出多条记录
///
///
///
public static IEnumerable Select(string sql)
{
return Db.Query(sql);
}
///
/// 查出一条记录的实体
///
///
///
///
public static T SelectFirst(string sql) where T : class, new()
{
return Db.QueryFirst(sql);
}
///
/// 查出多条记录的实体泛型集合
///
/// 泛型T
///
public static async Task> Select(string sql) where T : class, new()
{
return await Db.QueryAsync(sql);
}
public static async Task> Select(string sql, object obj) where T : class, new()
{
return await Db.QueryAsync(sql, obj);
}
///
/// 同时查询多张表数据(高级查询)
/// "select *from K_City;select *from K_Area";
///
///
///
public static SqlMapper.GridReader SelectMultiple(string sql)
{
return Db.QueryMultiple(sql);
}
///
/// 单,多表 更新(事务),执行原生sql
///
///
///
public static async Task Update(string sql)
{
int rows = 0;
using (IDbTransaction DbTransaction = Db.BeginTransaction())
{
try
{
rows = await Db.ExecuteAsync(sql, null, DbTransaction);
}
catch (DataException ex)
{
DbTransaction.Rollback();
}
DbTransaction.Commit();
}
return rows;
}
///
/// 单表批量更新(事务),泛型T集合作为参数
///
/// 泛型T
/// sql语句(sql="update Person set password='ddd' where id=@id",
/// 参数类(obj=new{id=1})
///
public static async Task Update(string sql, object obj) where T : class, new()
{
int rows = 0;
using (IDbTransaction DbTransaction = Db.BeginTransaction())
{
try
{
rows = await Db.ExecuteAsync(sql, obj, DbTransaction);
}
catch (DataException ex)
{
DbTransaction.Rollback();
}
DbTransaction.Commit();
}
return rows;
}
///
/// 多表 批量插入(事物),可以是泛型T集合数据
///
/// 二元组集合参数
///
public static int Update(List> param)
{
int rows = 0;
using (IDbTransaction DbTransaction = Db.BeginTransaction())
{
try
{
foreach (var item in param)
{
rows += Db.Execute(item.Item1, item.Item2, DbTransaction);
}
}
catch (DataException ex)
{
DbTransaction.Rollback();
}
DbTransaction.Commit();
}
return rows;
}
///
/// 单,多表删除(事物),原生sql
///
///
///
public static int Delete(string sql)
{
int rows = 0;
using (IDbTransaction DbTransaction = Db.BeginTransaction())
{
try
{
rows = Db.Execute(sql, null, DbTransaction);
}
catch (DataException ex)
{
DbTransaction.Rollback();
}
DbTransaction.Commit();
}
return rows;
}
///
/// 单表批量删除(事物),泛型T集合作为参数
///
///
///
///
///
public static int Delete(string sql, object obj) where T : class, new()
{
int rows = 0;
using (IDbTransaction DbTransaction = Db.BeginTransaction())
{
try
{
rows = Db.Execute(sql, obj, DbTransaction);
}
catch (DataException ex)
{
DbTransaction.Rollback();
}
DbTransaction.Commit();
}
return rows;
}
///
/// 多表批量删除(事物),可以是泛型T集合数据
///
/// 二元组参数
///
public static int Delete(List> param)
{
int rows = 0;
using (IDbTransaction DbTransaction = Db.BeginTransaction())
{
try
{
foreach (var item in param)
{
rows += Db.Execute(item.Item1, item.Item2, DbTransaction);
}
}
catch (DataException ex)
{
DbTransaction.Rollback();
}
DbTransaction.Commit();
}
return rows;
}
///
/// 单,多表插入(事物),原生sql
///
///
///
public static int Insert(string sql)
{
int rows = 0;
using (IDbTransaction DbTransaction = Db.BeginTransaction())
{
try
{
rows = Db.Execute(sql, null, DbTransaction);
}
catch (DataException ex)
{
DbTransaction.Rollback();
}
DbTransaction.Commit();
}
return rows;
}
///
/// 单表批量插入(事物),泛型T集合作为参数
///
///
///
///
///
public static int Insert(string sql, object obj) where T : class, new()
{
int rows = 0;
using (IDbTransaction DbTransaction = Db.BeginTransaction())
{
try
{
rows = Db.Execute(sql, obj, DbTransaction);
}
catch (DataException ex)
{
DbTransaction.Rollback();
}
DbTransaction.Commit();
}
return rows;
}
///
/// 多表批量插入(事物),可以是泛型T集合数据
///
/// 二元组参数
///
public static int Insert(List> param)
{
int rows = 0;
using (IDbTransaction DbTransaction = Db.BeginTransaction())
{
try
{
foreach (var item in param)
{
rows += Db.Execute(item.Item1, item.Item2, DbTransaction);
}
}
catch (DataException ex)
{
DbTransaction.Rollback();
}
DbTransaction.Commit();
}
return rows;
}
}
dapper支持异步操作,非常方便了。
这个层是对数据库表的映射,可以用t4模板或者其他的生成model,代码我就不贴出来了。
这个层是一些常用方法的封装,比如说IO操作,等等。
这个层是数据库访问层,针对单个model的一些操作。代码如下:
public class UserInfoResponsitory : IUserInfoResponsitory
{
public async Task> GetAllList()
{
string sql = "select Id, Name ,Age, Salary, DaptId, CreateTime,Pwd from user";
var list = await DbContexts.Select(sql);
return list;
}
public async Task AddUserInfo(UserInfo userinfo)
{
string query = "insert into user(Name, Age,Salary,DaptId,CreateTIme,Pwd) values(@name,@age,@salary,@daptid,@createtime,@pwd)";
int row = await DbContexts.Update(query, userinfo);
return row > 0;
}
public async Task updateUserInfo(UserInfo userinfo)
{
string query = "update user set name = @name where id = @id";
int row = await DbContexts.Update(query, userinfo);
return row > 0;
}
public async Task> GetUserInfoById(int id)
{
var user = await DbContexts.Select("select id,name, age, salary, daptId, createtime, pwd from user where id= @UserId", new { UserId = id });
return user;
}
public async Task> GetUserInfoList(int PageIndex, int PageSize)
{
string query = "select * from user limit @limitnumber,10";
var list = await DbContexts.Select(query, new { limitnumber = (PageIndex - 1) * 10 });
return list;
}
}
这个是数据库访问层的接口层,声明操作的方法,不实现
public interface IUserInfoResponsitory
{
Task> GetAllList();
#region 增加
///
/// 增加用户
///
///
///
Task AddUserInfo(UserInfo userinfo);
#endregion
#region 修改
///
///修改个人信息
///
///
///
Task updateUserInfo(UserInfo userinfo);
#endregion
///
/// 根据Id获取用户数据
///
///
///
Task> GetUserInfoById(int UserId);
///
/// 分页
///
///
///
///
Task> GetUserInfoList(int PageIndex, int PageSize);
我使用的是autofac的构造函数注入,代码如下:
var builder = new ContainerBuilder();
Type basetype = typeof(IDependency);
var assemblys = AppDomain.CurrentDomain.GetAssemblies().ToList();
var Allservices = assemblys.SelectMany(s => s.GetTypes())
.Where(p => basetype.IsAssignableFrom(p) && p != basetype);
builder.RegisterApiControllers(assemblys.ToArray());
builder.RegisterAssemblyTypes(assemblys.ToArray())
.Where(t => basetype.IsAssignableFrom(t) && t.IsClass )
.AsImplementedInterfaces().InstancePerRequest();
builder.RegisterType().As().InstancePerRequest();
var container = builder.Build();
var resolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
因为我用的是web api框架,所以引用autofac包的时候,要装下面几个包
由于时间有限,我这个框架搭的优点简单,应该在responsitory层上面加一个服务层,不暴露具体的数据库操作,只向外提供服务层的方法。
over