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,调用

 

posted @ 2019-08-08 15:26  代码驿站  阅读(2404)  评论(3编辑  收藏  举报