前言
一般情況下,使用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,調用