方式1:使用条件拼接的方式,有业务逻辑层传入拼接好的where条件
优点:通用性强,灵活。业务逻辑层很多的查询方法可以只调用dal的一个方法就行了
缺点:不面向对象,容易写错,容易出现sql注入问题、不能更换dal层,应为你按sqlserver的语法拼接where条件写在业务逻辑层,我换个mysql呢?
方式2:原始方式,在DAL中根据业务逻辑需要定义相应的查询
优点:在没有其它方案的时候比较倾向这种方式,因为dal层应该为bll层提供直观,简单的接口
缺点:通用性差,dal的类中可以出现很多重载,有需求变化是又要添加重载或添加、修改方法,代码量太多了
方式3:查询对象模式
优点:在不了解ORM之前,我认为这是最好的方式。BLL根据业务需要去创建查询对象,不同的DAL实现自己将这个查询对象解析成符合自己语法的sql条件语句。面向对象的方式
缺点:如果考虑某天DAL使用EF呢?那么需要将我们自己定义的查询对象再翻译成表达式树Expression,这玩意真心有点复杂,
方式4:自己实现IQueryProvider
个人感觉最好,最难的方式
EF没那么好用的. 我到现在都只在自己给别人做的项目里正经用了一下.
还是自己写的dal层好用.
你的数据访问层DAL的查询方法怎么定义的? 让BLL传过来拼接好的条件,还是为不同的查询定义不同的方法,还是别的方式?
@jionsoft: dal层都是自动生成的.具体用法是
db.表名.查询(m=>条件表达式) 这样
或者 db.表名.操作(new{新值},条件)
@吴瑞祥: 方便加个Q 截图我看看吗? 我的453008453
@jionsoft:
@吴瑞祥: 对啊,就想要这样的。这什么思路,用起来跟ef一样简单, 我说的方式4? 这不是用的ef吗?
@jionsoft: ef不是这样的.如果这种用法还不如别用ef.
ef的关键是对象关系映射.而不是对象表映射.一般人的用法都是在很表面的对象表映射.
我这个是直接封装了ormlite.虽然这些工具都叫orm.但其实都是表对象映射.
关系是关系不了的.
@吴瑞祥: 有点不太多,做.net也快5年了,这问题一直没搞太懂。一般接私活什么的,我直接用的EF,而且是强依赖,没有定义DAL层,BLL里直接用的DBContext。现在在做的项目用的简单三层,DAL用的Dapper,DAL里面类用定义的 完全是考虑BLL需要什么就定义什么, 参数也是根据BLL需要定义的,主要是类似仓储模式,BLL要什么就提供什么,问题是DAL会定义很多查询重载。
@jionsoft: 用ef的话就是直接用.不用封装的.我不用ef的问题在于他的并发处理实在是太麻烦了..
dal不用写查询重载的.我的dal层提供几个方法.
/// <summary> /// 命令基类.实现数据库操作 /// </summary> /// <typeparam name="T">要操作的表实体</typeparam> public class CommandBase<T> : QueryBase<T> where T : YW.Model.HasId { /// <summary> /// /// </summary> /// <param name="db"></param> public CommandBase(string db) : base(db) { } /// <summary> 插入一个实体 /// </summary> /// <param name="entity">要插入的实体</param> /// <returns>受影响的行数</returns> public long Insert(T entity) { using (var conn = DbConnFactory.Open(DbName)) { entity.Id = conn.Insert(entity, true); return entity.Id; } } /// <summary> 插入一个实体数组 /// </summary> /// <param name="entitys">要插入的实体数组</param> /// <returns>受影响的行数</returns> public int Insert(IEnumerable<T> entitys) { using (var conn = DbConnFactory.Open(DbName)) { if (DbSession.InDbTrasaction) { foreach (var entity in entitys) { entity.Id = conn.Insert(entity, true); } } else { using (var dt = conn.BeginTransaction()) { foreach (var entity in entitys) { entity.Id = conn.Insert(entity, true); } dt.Commit(); } } } return entitys.Count(); } /// <summary> 删除一个实体 /// </summary> /// <param name="id">要删除的实体id</param> /// <returns>受影响的行数</returns> public int Delete(long id) { using (var conn = DbConnFactory.Open(DbName)) { return conn.DeleteById<T>(id); } } /// <summary> 删除一个实体数组 /// </summary> /// <param name="ids">要删除的实体id数组</param> /// <returns>受影响的行数</returns> public int Delete(IEnumerable<long> ids) { using (var conn = DbConnFactory.Open(DbName)) { return conn.DeleteByIds<T>(ids); } } /// <summary> 根据条件删除 /// </summary> /// <param name="predicate">删除的条件表达式</param> /// <returns>受影响的行数</returns> public int Delete(Expression<Func<T, bool>> predicate) { using (var conn = DbConnFactory.Open(DbName)) { return conn.Delete(predicate); } } /// <summary> /// 根据id更新一个实体 /// </summary> /// <param name="entity">要更新的实体.</param> /// <returns>受影响的行数</returns> public int Update(T entity) { using (var conn = DbConnFactory.Open(DbName)) { return conn.Update(entity); } } /// <summary> /// 根据id更新一个实体数组 /// </summary> /// <param name="entitys">要更新的实体数组.</param> /// <returns>受影响的行数</returns> public int Update(IEnumerable<T> entitys) { using (var conn = DbConnFactory.Open(DbName)) { if (DbSession.InDbTrasaction) { foreach (var item in entitys) { conn.Update(item); } } else { using (var dt = conn.BeginTransaction()) { foreach (var item in entitys) { conn.Update(item); } dt.Commit(); } } } return entitys.Count(); } /// <summary> /// 根据条件更新部分字段 /// </summary> /// <param name="fields"></param> /// <param name="predicate"></param> /// <returns></returns> public int Update(object fields, Expression<Func<T, bool>> predicate) { using (var conn = DbConnFactory.Open(DbName)) { return conn.Update(fields, predicate); } } /// <summary> /// 增量更新方法 /// 例子:UpdateAdd(()=>new T{Field=1(或者-1)},m=>条件表示) /// </summary> /// <param name="updateFields">要修改的字段和增量值,不修改的字段不赋值</param> /// <param name="where">条件表达式</param> /// <returns></returns> public int UpdateAdd(Expression<Func<T>> updateFields, Expression<Func<T, bool>> where = null) { using (var conn = DbConnFactory.Open(DbName)) { return conn.UpdateAdd(updateFields, where); } } }
public class QueryBase<T> where T : YW.Model.HasId { protected string DbName; public QueryBase(string db) { DbName = db; } /// <summary> /// 获取所有记录 /// </summary> /// <returns></returns> public IEnumerable<T> SelectAll() { using (var conn = DbConnFactory.Open(DbName)) { return conn.Select<T>(); } } public T Single(long id) { using (var conn = DbConnFactory.Open(DbName)) { return conn.SingleById<T>(id); } } public T Single(Expression<Func<T, bool>> predicate) { using (var conn = DbConnFactory.Open(DbName)) { return conn.Single(predicate); } } public T Single(Action<SqlExp<T>> expression) { using (var conn = DbConnFactory.Open(DbName)) { var exp = SqlExp<T>.GetSqlExp(conn); expression(exp); return conn.Single(exp.GetExp()); } } public IEnumerable<T> Where(IEnumerable<long> ids) { using (var conn = DbConnFactory.Open(DbName)) { return conn.SelectByIds<T>(ids); } } public IEnumerable<T> Where(Expression<Func<T, bool>> predicate) { using (var conn = DbConnFactory.Open(DbName)) { var result = conn.Select(predicate); return result; } } public IEnumerable<T> Where(Action<SqlExp<T>> expression) { using (var conn = DbConnFactory.Open(DbName)) { var exp = SqlExp<T>.GetSqlExp(conn); expression(exp); var r = conn.Select(exp.GetExp()); var sql = conn.GetLastSql(); sql += ""; return r; } } public int Count(Expression<Func<T, bool>> predicate) { using (var conn = DbConnFactory.Open(DbName)) { return (int)conn.Count(predicate); } } public int Count(Action<SqlExp<T>> expression) { using (var conn = DbConnFactory.Open(DbName)) { var exp = SqlExp<T>.GetSqlExp(conn); expression(exp); return (int)conn.Count<T>(exp.GetExp()); } } public bool Any(Expression<Func<T, bool>> predicate) { return (Count(predicate) > 0); } public PagedResultModel<T> QueryPage( Expression<Func<T, bool>> where, Expression<Func<T, object>> orderByKeySelector = null, bool isDesc = false, int pageIndex = 1, int pageSize = 20) { var result = new PagedResultModel<T> { Page = pageIndex, PageSize = pageSize, RowCount = Count(where), Body = Where(m => { m.And(where); if (orderByKeySelector != null) { if (isDesc) { m.OrderByDescending(orderByKeySelector); } else { m.OrderBy(orderByKeySelector); } } m.Limit((pageIndex - 1) * pageSize, pageSize); }) }; return result; } public PagedResultModel<T> QueryPage( Action<SqlExp<T>> expression, Expression<Func<T, object>> orderByKeySelector = null, bool isDesc = false, int pageIndex = 1, int pageSize = 20) { var result = new PagedResultModel<T> { Page = pageIndex, PageSize = pageSize, RowCount = Count(expression), Body = Where(m => { expression(m); if (orderByKeySelector != null) { if (isDesc) { m.OrderByDescending(orderByKeySelector); } else { m.OrderBy(orderByKeySelector); } } m.Limit((pageIndex - 1) * pageSize, pageSize); }) }; return result; } public TKey Sum<TKey>(Expression<Func<T, object>> field, Expression<Func<T, bool>> predicate) { using (var conn = DbConnFactory.Open(DbName)) { var exp = conn.GetDialectProvider().SqlExpression<T>(); exp.Select(Sql.Sum(exp.ModelDef.GetFieldDefinition(field).FieldName)); exp.And(predicate); var result = conn.Scalar<TKey>(exp); return result; } } }
@吴瑞祥: 其实我就是想要你这种方式,不依赖EF,又跟EF一样简单的语法
public int Delete(Expression<Func<T, bool>> predicate) { using (var conn = DbConnFactory.Open(DbName)) { return conn.Delete(predicate); } }
predicate这个参数是怎么转换成最终sql条件语句的,用的什么框架还是自己解析表达式树?
对EF并发我不太了解,包括数据库并发。不过我觉得EF都到6了,微软也花这么多力气。 用起来真心挺省事。建议还是再花点时间找找EF并发的解决办法。 没有特殊要求其实EF开发起来很省事。我一般会选用EF,但是不想项目依赖它
@jionsoft: 我这个是封装了ORMLITE的.
ef是好.并且并发也有解决方案.但是不好用.
@吴瑞祥: 朋友~ 感谢哈。非常感谢~
@jionsoft: 我觉得这样虽然麻烦,那比较好容易更换DAL阿