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.測試接口:





