ASP.NET WebApi项目框架搭建(六):数据库ORM之Sqlsugar
一、前言
SqlSugar是国人开发者开发的一款基于.NET的ORM框架,是可以运行在.NET 4.+ & .NET CORE的高性能、轻量级 ORM框架,众多.NET框架中最容易使用的数据库访问技术。官网http://www.codeisbug.com/Doc/8
SqlSugar的优点:
1、高性能 ,不夸张的说,去掉Sql在数据库执行的时间,SqlSugar是EF数倍性能,另外在批量操作和一对多查询上也有不错的SQL优化
2、高扩展性 ,支持自定义拉姆达函数解析、扩展数据类型、支持自定义实体特性,外部缓存等
3、稳定性和技术支持, 虽然不是官方ORM, 但在稳定性上也是有着数年用户积累,如果遇到问题可以在GITHUB提出来,会根据紧急度定期解决
4、功能全面,虽然SqlSugar小巧可功能并不逊色于EF框架
5、创新、持续更新 ,向下兼容
二、项目架构
ASP.NET项目,常常会用到分层的概念,常用的有三层架构(DAL,DLL,UIL),在此基础上,我又细分下,下面是我的项目架构:
1.webapi:主项目层
主项目层主要用来放置控制器和一些插件的配置,过滤器,异常处理等。
控制器除了偶尔会做一些参数是否为空的验证外(有人认为验证也不应该在控制器层做,因人而异),其他不做任何操作,只是将参数传给下一层业务逻辑层处理。
2.IRepository:业务逻辑接口层
该层为业务逻辑接口层,里面只罗列了相应的接口函数,但是具体的函数功能实现则交给继承该数据接口的业务逻辑层来实现。
3.Repository:业务逻辑层
业务逻辑层接收到控制器层传递的参数后,将这些参数做相应的处理,然后将加工后的参数传给下一层:数据接口层。(按照比较简单的三层架构思想,其实应该直接传给数据层,但是这里利用数据接口层做了一个分隔,好处后面慢慢就会发现了)
4..IService 数据接口层
该层为数据接口层,里面只罗列了相应的接口函数,但是具体的函数功能实现则交给继承该数据接口的数据层来实现。
这样做的好处是可以将数据库操作与代码逻辑操作分离的更加清晰。
5.Service 数据层
该层负责直接或者间接对数据库进行操作,如果你是用原生的或者类似Dapper的数据库中间件,那么在这一层就会看到相应的sql语句(当然,这里我们选择了集成SqlSugar作为数据库操作中间件)。
该层继承了相应的数据接口,所以必须实现接口内的所有函数。
6.Entity 实体层
该层为实体类层,存储了数据库对应的所有实体,实体一般和数据库表是一一对应的。
6.Common 公共层
该层存放了一些系统帮助类,或是实体辅助类。
三、操作sqlserver数据库
1.数据库创建t_user表
Id设置为主键,并设置自增长。
2.添加几条数据:
三、使用Sqlsugar实现CURD
1.Common库使用Nuget安装Sqlsugar
2.新建个DB文件夹,创建数据库初始化类DbContext
public class DbContext<T> where T : class, new()
{
public DbContext()
{
Db = new SqlSugarClient(new ConnectionConfig()
{
ConnectionString = "server=.;uid=sa;pwd=sa123;database=test",
DbType = DbType.SqlServer,
InitKeyType = InitKeyType.Attribute,//从特性读取主键和自增列信息
IsAutoCloseConnection = true,//开启自动释放模式和EF原理一样我就不多解释了
});
}
//注意:不能写成静态的
public SqlSugarClient Db;//用来处理事务多表查询和复杂的操作
public SimpleClient<T> SimpleDb { get { return new SimpleClient<T>(Db); } }//用来处理t表的常用操作
3.Enity实体类也安装Sqlsugar并新建User实体
[SugarTable("t_user")]
public class User
{
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)] //是主键, 还是标识列
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
4.autofac注册Server层和Repository层
//WebAPI只用引用services和repository的接口,不用引用实现的dll。
//如需加载实现的程序集,将dll拷贝到bin目录下即可,不用引用dll
var iService = Assembly.Load("hgd.IService");
var service = Assembly.Load("hgd.Service");
var IRepository = Assembly.Load("hgd.IRepository");
var repository = Assembly.Load("hgd.Repository");
//根据名称约定(服务层的接口和实现均以Services结尾),实现服务接口和服务实现的依赖
builder.RegisterAssemblyTypes(iService, service)
.Where(t => t.Name.EndsWith("Service")).AsSelf()
.AsImplementedInterfaces();
builder.RegisterAssemblyTypes(IRepository, repository)
.Where(t => t.Name.EndsWith("Repository")).AsSelf().AsImplementedInterfaces();
5.Common层新建TableModel类用以定义列表查询返回模板
public class TableModel<T>
{
/// <summary>
/// 数量
/// </summary>
public int count { get; set; }
/// <summary>
/// 总数
/// </summary>
public int totalNumber { get; set;}
/// <summary>
/// 总页数
/// </summary>
public int totalPage { get; set; }
/// <summary>
/// 数据列表
/// </summary>
public List<T> data { get; set; }
}
}
6.Common层新建Page类用以定义分页信息
public class Page
{
/// <summary>
/// 是否第一页
/// </summary>
public bool is_first_page;
/// <summary>
/// 是否最后一页
/// </summary>
public bool is_last_page;
/// <summary>
/// 第几页
/// </summary>
public int page_no;
/// <summary>
/// 每页多少条
/// </summary>
public int page_size;
/// <summary>
/// 总量
/// </summary>
public int total_count;
/// <summary>
/// 总页数
/// </summary>
public int total_page;
}
7.Common层新建MessageModel类用以定义消息返回模板
public class MessageModel<T>
{
/// <summary>
/// 返回码
/// </summary>
public int code { get; set; }
/// <summary>
/// 消息
/// </summary>
public string msg { get; set; }
/// <summary>
/// 数据
/// </summary>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public List<T> data { get; set; }
/// <summary>
/// 分页信息
/// </summary>
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public Page page { get; set; }
}
7.Iservice定义数据接口IUserService
public interface IUserService
{
/// <summary>
/// 获取分页列表
/// </summary>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
TableModel<User> GetPageList(int pageIndex, int pageSize);
/// <summary>
/// 获取单个
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
User Get(long id);
/// <summary>
/// 添加
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
bool Add(User entity);
/// <summary>
/// 编辑
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
bool Update(User entity);
/// <summary>
/// 批量删除
/// </summary>
/// <param name="ids"></param>
/// <returns></returns>
bool Dels(dynamic[] ids);
}
8.Service层实现接口
public class UserService : DbContext<User>, IUserService
{
private ILog _log;
public UserService(ILog log)
{
_log = log;
//打印sql
Db.Aop.OnLogExecuting = (sql, pars) =>
{
_log.Debug(sql + "\r\n" +
Db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));
};
}
public bool Add(User entity)
{
return SimpleDb.Insert(entity);
}
public bool Dels(dynamic[] ids)
{
return SimpleDb.DeleteByIds(ids);
}
public User Get(long id)
{
return SimpleDb.GetById(id);
}
public TableModel<User> GetPageList(int pageIndex, int pageSize)
{
int totalNumber = 0;
int totalPage = 0;
List<User> data = SimpleDb.AsQueryable().Where(t => t.Age == 12).ToPageList(pageIndex, pageSize, ref totalNumber, ref totalPage);
Page page = Utils.GetPage(pageIndex, pageSize, totalNumber, totalPage);
return new TableModel<User>() { count = data.Count, page = page, data = data };
}
public bool Update(User entity)
{
return SimpleDb.Update(entity);
}
}
9.IRepository层定义业务逻辑接口
public interface IUserRepository
{
User GetById(long id);
MessageModel<User> GetPageList(int pageIndex, int pageSize);
MessageModel<User> Add(User entity);
MessageModel<User> Update(User entity);
MessageModel<User> Dels(dynamic[] ids);
}
10.Repository层实现接口
public class UserRepository : IUserRepository
{
public IUserService _IUser;
public UserRepository(UserService userService)
{
_IUser = userService;
}
public MessageModel<User> Add(User entity)
{
if (_IUser.Add(entity))
return new MessageModel<User> { code = (int)HttpCode.OK, msg = "操作成功" };
else
return new MessageModel<User> { code = (int)HttpCode.FAILED, msg = "操作失败" };
}
public MessageModel<User> Dels(dynamic[] ids)
{
if (_IUser.Dels(ids))
return new MessageModel<User> { code = (int)HttpCode.OK, msg = "操作成功" };
else
return new MessageModel<User> { code = (int)HttpCode.FAILED, msg = "操作失败" };
}
public User GetById(long id)
{
return _IUser.Get(id);
}
public MessageModel<User> Update(User entity)
{
if (_IUser.Update(entity))
return new MessageModel<User> { code = (int)HttpCode.OK, msg = "操作成功" };
else
return new MessageModel<User> { code = (int)HttpCode.FAILED, msg = "操作失败" };
}
MessageModel<User> IUserRepository.GetPageList(int pageIndex, int pageSize)
{
var data = _IUser.GetPageList(pageIndex, pageSize);
MessageModel<User> user = new MessageModel<User>();
user.code = (int)HttpCode.OK;
user.msg = "ok";
user.page = user.page;
user.data = data.data;
return user;
}
}
11.新建控制器Sqlsugar
[RoutePrefix("api/sql")]
public class SqlSugarController : ApiController
{
private IUserRepository _user;
public SqlSugarController(UserRepository userRepository)
{
_user = userRepository;
}
[HttpPost]
[Route("add")]
public IHttpActionResult Add([FromBody]User user)
{
if (user == null)
return Json(new MessageModel<User>() { code = (int)HttpCode.NULL_PARAM, msg = "参数为空" });
return Json(_user.Add(user));
}
[HttpPost]
[Route("del")]
public IHttpActionResult Dels ([FromBody]dynamic[] ids)
{
if (ids.Length == 0)
return Json(new MessageModel<User>() { code = (int)HttpCode.NULL_PARAM, msg = "参数为空" });
return Json(_user.Dels(ids));
}
[HttpPut]
[Route("update")]
public IHttpActionResult Update([FromBody]User user)
{
if (user == null)
return Json(new MessageModel<User>() { code = (int)HttpCode.NULL_PARAM, msg = "参数为空" });
return Json(_user.Update(user));
}
[HttpGet]
[Route("getuser")]
public IHttpActionResult Getuser(int pageIndex = 1, int pageSize = 10)
{
return Json(_user.GetPageList(pageIndex, pageSize));
}
}
12.测试接口: