ABP实现EF执行SQL(增删改查)解决方案
前言
一般情况下,使用EF中的语法可以帮助我们完成绝大部分业务,但是也有特殊的情况需要直接执行的Sql语句。比如,我们的业务过于复杂繁琐,或是有些业务使用EF操作时比较复杂,但是使用的Sql时会很简单等,这时就有了以下需求了。
具体实现
1,首先我们需要定义一个接口类:ISqlExecuter(名字看你心情了)
1 public interface ISqlExecuter 2 { 3 /// <summary> 4 /// 执行给定的命令 5 /// </summary> 6 /// <param name="sql">命令字符串</param> 7 /// <param name="parameters">要应用于命令字符串的参数</param> 8 /// <returns>执行命令后由数据库返回的结果</returns> 9 int Execute(string sql); 10 11 /// <summary> 12 /// 传入查询sql,返回List<T>数组 13 /// </summary> 14 /// <param name="sql"></param> 15 /// <returns></returns> 16 Task<List<T>> SqlQuery<T>(string sql) where T : class, new(); 17 }
2,定义实现类:SqlExecuter(名字看你心情了)
1 public class SqlExecuter : ISqlExecuter, ITransientDependency 2 { 3 private IDbContextProvider<OADbContext> _dbContextProvider = null; 4 5 public SqlExecuter(IDbContextProvider<OADbContext> dbContextProvider) 6 { 7 _dbContextProvider = dbContextProvider;//IocManager.Instance.Resolve<IDbContextProvider<OADbContext>>(); 8 } 9 10 /// <summary> 11 /// 执行给定的命令 12 /// </summary> 13 /// <param name="sql">命令字符串</param> 14 /// <param name="parameters">要应用于命令字符串的参数</param> 15 /// <returns>执行命令后由数据库返回的结果</returns> 16 public int Execute(string sql) 17 { 18 return _dbContextProvider.GetDbContext().Database.ExecuteSqlCommand(new RawSqlString(sql)); 19 } 20 21 /// <summary> 22 /// 传入查询sql,返回List<T>数组 23 /// </summary> 24 /// <param name="sql"></param> 25 /// <returns></returns> 26 public async Task<List<T>> SqlQuery<T>(string sql) where T : class, new() 27 { 28 return await Task.Run(() => 29 { 30 var db = _dbContextProvider.GetDbContext().Database; 31 var conn = db.GetDbConnection(); 32 if (conn.State != ConnectionState.Open) 33 conn.Open(); 34 35 var result = new List<T>(); 36 37 try 38 { 39 RelationalDataReader query = null; 40 41 using (db.GetService<IConcurrencyDetector>().EnterCriticalSection()) 42 { 43 var rawSqlCommand = db.GetService<IRawSqlCommandBuilder>().Build(sql); 44 45 query = rawSqlCommand.ExecuteReader(db.GetService<IRelationalConnection>()); 46 } 47 48 //获取DbDataReader 49 var dr = query.DbDataReader; 50 51 var properties = typeof(T).GetProperties().ToList(); 52 53 while (dr.Read()) 54 { 55 var obj = new T(); 56 foreach (var property in properties) 57 { 58 //获取该字段明的列序号,从0开始 59 var id = dr.GetOrdinal(property.Name.ToLower()); 60 61 if (!dr.IsDBNull(id)) 62 { 63 if (dr.GetValue(id) != DBNull.Value) 64 { 65 property.SetValue(obj, dr.GetValue(id)); 66 } 67 } 68 } 69 70 result.Add(obj); 71 } 72 73 //关闭DbDataReader 74 dr.Close(); 75 } 76 catch (Exception e) 77 { 78 throw new UserFriendlyException(e.Message); 79 } 80 81 return result; 82 }); 83 } 84 }
注意:
引用ITransientDependency接口是为了ABP的自动注册到容器。
使用方式
1,注入实例:
2,调用