ABP实现EF执行SQL(增删改查)解决方案
前言
一般情况下,使用EF中的语法可以帮助我们完成绝大部分业务,但是也有特殊的情况需要直接执行的Sql语句。比如,我们的业务过于复杂繁琐,或是有些业务使用EF操作时比较复杂,但是使用的Sql时会很简单等,这时就有了以下需求了。
具体实现
1,首先我们需要定义一个接口类:ISqlExecuter(名字看你心情了)
1 public interface ISqlExecuter 2 { 3 ///接口类4 /// 执行给定的命令 5 /// 6 /// 命令字符串 7 /// 要应用于命令字符串的参数 8 /// 执行命令后由数据库返回的结果 9 int Execute(string sql); 10 11 /// 12 /// 传入查询sql,返回List 数组 13 /// 14 /// 15 /// 16 Task > SqlQuery
(string sql) where T : class, new(); 17 }
2,定义实现类:SqlExecuter(名字看你心情了)
1 public class SqlExecuter : ISqlExecuter, ITransientDependency 2 { 3 private IDbContextProvider接口实现代码_dbContextProvider = null; 4 5 public SqlExecuter(IDbContextProvider dbContextProvider) 6 { 7 _dbContextProvider = dbContextProvider;//IocManager.Instance.Resolve >(); 8 } 9 10 ///11 /// 执行给定的命令 12 /// 13 /// 命令字符串 14 /// 要应用于命令字符串的参数 15 /// 执行命令后由数据库返回的结果 16 public int Execute(string sql) 17 { 18 return _dbContextProvider.GetDbContext().Database.ExecuteSqlCommand(new RawSqlString(sql)); 19 } 20 21 /// 22 /// 传入查询sql,返回List 数组 23 /// 24 /// 25 /// 26 public async Task > SqlQuery
(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 (); 36 37 try 38 { 39 RelationalDataReader query = null; 40 41 using (db.GetService ().EnterCriticalSection()) 42 { 43 var rawSqlCommand = db.GetService ().Build(sql); 44 45 query = rawSqlCommand.ExecuteReader(db.GetService ()); 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,调用