前言
后端开发最常打交道的就是数据库了(静态网站靠边),上一篇net core Webapi基础工程搭建(五)——缓存机制,缓存就是为了减少数据库的读操作,不过什么访问都是会耗时的,拿空间(内存)换时间对用户体验来说是惯用手段,后续介绍界面操作的时候再说用户体验。
SqlSugar
当然你可以用EF(太重,扩展性相对差,但不可否认基本上涵盖范围够广),也可以用Dapper(这个我之前头一回鼓捣net core的时候用的是Dapper),或者自己基于原生去写数据库的操作,都Ok,但是如果有造好的轮子,对于我们来说用就行了,可以深入理解但对于常规开发来说,CV大法是最好的(新手向),SqlSugar的文档地址。
之前的工程在最初创建的时候,没有创建完整,因为当时不操作数据层,所以偷个懒,这次一并创建,具体过程不再赘述
,同April.Util工程的创建一致,都是类库项目,新建April.Service,April.Entity。
好了,我们在Service与Entity项目中通过NuGet包引入sqlSugarCore,至于原因前面也说过net core Webapi基础工程搭建(四)——日志功能log4net。
这里应该不需要再图文介绍引入了,如果不清楚,也可以去上面的链接查看NuGet的引入方法。
引入完成后,我们在Entity项目创建一个类对象,命名为StudentEntity吧,只是做个示例。
1 2 3 4 5 6 7 8 9
| public class StudentEntity { private int _ID = -1; private string _Name = string.Empty; private string _Number = string.Empty; private int _Age = 0; private int _Sex = 0; private string _Address = string.Empty; }
|
对象属性这块儿,看个人习惯,有些人偏向于直接get,set方法,我习惯于先初始化,选中所有的私有属性,使用宇宙第一IDE的快捷键Ctrl+R+E,点击确定,好了自己去加注释去吧。
这里也说下为什么Entity这个实例对象层也要引入SqlSugar,是因为如果你的表名或者属性名与数据库不一致的时候,还是需要标识出来的,比如下面的代码,具体的用法还是去参考文档吧,我这只是轻描淡写下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| [SugarTable("test_Student")] public class StudentEntity { private int _ID = -1; private string _Name = string.Empty; private string _Number = string.Empty; private int _Age = 0; private int _Sex = 0; private string _Address = string.Empty;
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int ID { get => _ID; set => _ID = value; } public string Name { get => _Name; set => _Name = value; } public string Number { get => _Number; set => _Number = value; } public int Age { get => _Age; set => _Age = value; } public int Sex { get => _Sex; set => _Sex = value; } [SugarColumn(ColumnName = "test_Address")] public string Address { get => _Address; set => _Address = value; } }
|
实体对象我就不多写了,重复的工作是根据你自己的业务所处理的。
Service层
这个地方我重点标注下,是因为数据库这块儿的操作还是需要重视的,我们先来新建个BaseDbContext用于执行数据库操作的实体。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| public class BaseDbContext { public SqlSugarClient Db; public BaseDbContext(string connStr, int sqlType = 1) { InitDataBase(connStr, sqlType); }
public BaseDbContext(string serverIp, string user, string pass, string dataBase) { string connStr = $"server={serverIp};user id={user};password={pass};persistsecurityinfo=True;database={dataBase}"; InitDataBase(connStr); }
private void InitDataBase(string connStr, int sqlType = 1) { Db = new SqlSugarClient(new ConnectionConfig() { ConnectionString = connStr, DbType = (DbType)sqlType, IsAutoCloseConnection = true, }); Db.Ado.CommandTimeOut = 30000; Db.Aop.OnLogExecuted = (sql, pars) => { }; Db.Aop.OnLogExecuting = (sql, pars) => { }; Db.Aop.OnError = (exp) => { }; Db.Aop.OnExecutingChangeSql = (sql, pars) => { return new KeyValuePair<string, SugarParameter[]>(sql, pars); }; } public void BeginTran() { Db.Ado.BeginTran(); } public void CommitTran() { Db.Ado.CommitTran(); } public void RollbackTran() { Db.Ado.RollbackTran(); } }
|
构造函数主要用于实例化你的数据库对象(连接串,数据库类型),日志的记录,事务这些也都标注上,后续可以替换直接使用。
BaseService(基类)
在最初写net core的时候,我用Repository层来实现sql处理,Service用来做逻辑处理,传统的三层架构,但是对于简单的工程来说,个人感觉Bll层的存在不是那么理想,可能是我没彻底理解三层架构吧,这个地方如果有个人想法或好的见解也希望一块交流,互相进步。
在写基类之前,我们在Util层新建一个SqlSqlFilterEntity,这步可能算是多此一举,但是为了减少团队其他人的学习成本,我还是写了这个对象,以致于后续的封装,会以此为参数做传递而不公开lambda的写法使用。
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class SqlFilterEntity { private string _Filter = string.Empty; private Dictionary<string, object> _Value = null; public string Filter { get => _Filter; set => _Filter = value; } public Dictionary<string, object> Value { get => _Value; set => _Value = value; } }
|
在Service层新建IBaseService接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| public interface IBaseService<T> : IDisposable { List<T> GetPageList(int pageIndex, int pageSize, string strField, SqlFilterEntity filter, string strOrder, out int totalCount);
ISugarQueryable<T> GetList(string field, SqlFilterEntity filter);
ISugarQueryable<T> GetList(int top = 0);
T GetEntity(SqlFilterEntity filter, string field = "");
bool IsExists(SqlFilterEntity filter);
int Insert(T entity, List<string> ignoreColumns = null, bool isLock = false);
bool Update(T entity, List<string> ignoreColumns = null, bool isLock = false);
bool Delete(T entity, bool isLock = false);
}
|
可以看到,我通过SqlFilterEntity这一实例来传递我的Where条件。
实现接口方法,新建BaseService。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
| public class BaseService<T> : IBaseService<T> where T : class, new() { private BaseDbContext baseDb; protected SqlSugarClient db;
public BaseService() { baseDb = new BaseDbContext("你的数据库连接"); db = baseDb.Db; }
public List<T> GetPageList(int pageIndex, int pageSize, string strField, SqlFilterEntity filter, string strOrder, out int totalCount) { totalCount = 0; if (pageIndex <= 0) { pageIndex = 1; } if (pageSize <= 0) { pageSize = 10; } if (string.IsNullOrEmpty(strField)) { strField = ""; } if (string.IsNullOrEmpty(strOrder)) { strOrder = string.Format("ID asc"); } if (filter == null) { filter = new SqlFilterEntity(); } return db.Queryable<T>().With(SqlWith.NoLock).Select(strField).WhereIF(!string.IsNullOrEmpty(filter.Filter), filter.Filter, filter.Value).OrderByIF(!string.IsNullOrEmpty(strOrder), strOrder).ToPageList(pageIndex, pageSize, ref totalCount); }
public ISugarQueryable<T> GetList(string field, SqlFilterEntity filter) { if (string.IsNullOrEmpty(field)) { field = ""; } if (filter == null) { filter = new SqlFilterEntity(); } return db.Queryable<T>().With(SqlWith.NoLock).Select(field).WhereIF(!string.IsNullOrEmpty(filter.Filter), filter.Filter, filter.Value); }
public ISugarQueryable<T> GetList(int top = 0) { if (top > 0) { return db.Queryable<T>().With(SqlWith.NoLock).Take(top); } else { return db.Queryable<T>().With(SqlWith.NoLock); } }
public T GetEntity(SqlFilterEntity filter, string field = "") { if (string.IsNullOrEmpty(field)) { field = ""; } if (filter != null) { return db.Queryable<T>().With(SqlWith.NoLock).Select(field).WhereIF(!string.IsNullOrEmpty(filter.Filter), filter.Filter, filter.Value).First(); } return default(T); }
public bool IsExists(SqlFilterEntity filter) { var result = db.Queryable<T>().With(SqlWith.NoLock).WhereIF(!string.IsNullOrEmpty(filter.Filter), filter.Filter, filter.Value).Count(); return result > 0; }
public int Insert(T entity, List<string> ignoreColumns = null, bool isLock = false) { if (ignoreColumns == null) { ignoreColumns = new List<string>(); } var result = isLock ? db.Insertable(entity).With(SqlWith.UpdLock).IgnoreColumns(ignoreColumns.ToArray()).ExecuteReturnIdentity() : db.Insertable(entity).IgnoreColumns(ignoreColumns.ToArray()).ExecuteReturnIdentity(); return result; }
public bool Update(T entity, List<string> ignoreColumns = null, bool isLock = false) { if (ignoreColumns == null) { ignoreColumns = new List<string>(); } var result = isLock ? db.Updateable(entity).With(SqlWith.UpdLock).IgnoreColumns(ignoreColumns.ToArray()).ExecuteCommand() : db.Updateable(entity).IgnoreColumns(ignoreColumns.ToArray()).ExecuteCommand(); return result > 0; }
public bool Delete(T entity, bool isLock = false) { var result = isLock ? db.Deleteable<T>(entity).With(SqlWith.RowLock).ExecuteCommand().ObjToBool() : db.Deleteable<T>(entity).ExecuteCommand().ObjToBool(); return result; }
public void Dispose() {
} }
|
小结
这一篇感觉写的不多,但是代码放的有点儿多,习惯性的把东西尽可能介绍详细点儿,万一有人真的从小白开始一点点儿想折腾个啥东西呢(比如说我),下一篇Part 2介绍具体的用法和测试吧。