9.18 Sql 高级代理
📝 模块更新日志
-
新特性
-
Sql
高级拦截支持返回IEnumerable<T>
和T[]
类型值 4.8.7.5 ⏱️2023.03.07 f2ca2d3
-
查看变化
过去版本如果返回对象类型只支持 List<T>
,T
和 Tuple<>
,现已支持 IEnumerable<T>
、T[]
和 Tuple<>
混合体。
public interface ISql : ISqlDispatchProxy
{
[SqlExecute("select * from person")]
Person[] GetPersons();
[SqlExecute("select * from person")]
IEnumerable<Person> GetPersons2();
// 更复杂的组合
[SqlExecute(@"
select * from person where id = 1;
select * from person;
select * from person where id > 0;
select * from person where id > 0;
")]
(Person, List<Person>, Person[], IEnumerable<Person>) GetPersons();
}
9.18.1 关于 Sql
代理
Sql
代理是 Furion
框架中对 Sql
操作一个非常重要的概念,通过这种方式可以大大提高 Sql
书写效 率,而且后期极易维护。
Sql
代理属于 Furion
框架中一个高级功能。
9.18.2 了解 ISqlDispatchProxy
ISqlDispatchProxy
接口是 Furion
实现被代理接口的唯一依赖,任何公开的接口一旦集成了 ISqlDispatchProxy
接口,那么这个接口就是被托管拦截的 Sql
操作接口。
简单定义一个 Sql 代理接口
using Furion.DatabaseAccessor;
namespace Furion.Application
{
public interface ISql : ISqlDispatchProxy
{
}
}
一旦这个接口继承了 ISqlDispatchProxy
,那么它就会动态创建接口实例,而且支持依赖注入/控制反转获取实例。
9.18.3 开始领略 Sql
代理
下面我将通过多个例子来演示 Sql
代理的用法,为什么推荐这种方式操作 Sql
。
支持各种方式获取实例:
9.18.3.1 构造函数方式
private readonly ISql _sql;
public FurionService(ISql sql)
{
_sql = sql;
}
9.18.3.2 方法参数注入
public async Task<List<PersonDto>> GetAll([FromServices] ISql, string keyword)
{
}
9.18.3.3 Db.GetSqlDispatchProxy<ISql>()
var sql = Db.GetSqlDispatchProxy<ISql>();
9.18.4 Sql
操作
9.18.4.1 返回 DataTable
using Furion.DatabaseAccessor;
namespace Furion.Application
{
public interface ISql : ISqlDispatchProxy
{
// 执行sql并传入参数,基元类型
[SqlExecute("select * from person where id >@id and name like @name")]
DataTable GetPerson(int id, string name);
// 执行sql并传入参数,对象类型
[SqlExecute("select * from person where id >@id and name like @name")]
DataTable GetPerson(MyParam paras);
// 执行存储过程 sql,支持设置参数类型
[SqlExecute("exec PROP_NAME @id", CommandType = CommandType.StoredProcedure)]
DataTable GetPerson(int id);
// 支持多数据库操作
[SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator))]
DataTable GetPerson();
// 异步方式
[SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator))]
Task<DataTable> GetPersonAsync();
}
}
关于参数
Sql
代理参数查找规则:
如果方法的参数是 基元类型
(或 string
、值类型
),则自动将这些类型组合成 Dictionary<string, object>
作为 Sql
参数。命令参数可使用方法同名参数加 @
符号。
如果方法的参数是 类类型
,那么自动遍历该类公开实例属性生成 DbParameter[]
数组,每一个属性名都将是命令参数,大部分数据库是不区分大小写,个别数据库除外,如 Sqlite
,如:
public class MyModel
{
public int Id {get;set;}
public string Name {get; set;}
}
那么 sql
语句可以直接使用属性名作为参数:
select * from person where id > @id and name = @name;
9.18.4.2 返回 List<T>
using Furion.DatabaseAccessor;
namespace Furion.Application
{
public interface ISql : ISqlDispatchProxy
{
// 执行sql并传入参数,基元类型
[SqlExecute("select * from person where id >@id and name like @name")]
List<Person> GetPerson(int id, string name);
// 执行sql并传入参数,对象类型
[SqlExecute("select * from person where id >@id and name like @name")]
List<Person> GetPerson(MyParam paras);
// 执行存储过程 sql,支持设置参数类型
[SqlExecute("exec PROP_NAME @id", CommandType = CommandType.StoredProcedure)]
List<Person> GetPerson(int id);
// 支持多数据库操作
[SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]
List<Person> GetPerson();
// 异步方式
[SqlExecute("select * from person"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]
Task<List<Person>> GetPersonAsync();
}
}
9.18.4.3 返回 DataSet
using Furion.DatabaseAccessor;
namespace Furion.Application
{
public interface ISql : ISqlDispatchProxy
{
// 执行sql并传入参数,基元类型
[SqlExecute(@"
select * from person where id >@id and name like @name;
select top 10 * from student where Id >@id;")]
DataSet GetData(int id, string name);
// 执行sql并传入参数,对象类型
[SqlExecute(@"
select * from person where id >@id and name like @name;
select top 10 * from student where Id >@id;")]
DataSet GetData(MyParam paras);
// 执行存储过程 sql,支持设置参数类型
[SqlExecute(@"
exec PROP_NAME @id;
select * from person;", CommandType = CommandType.StoredProcedure)]
DataSet GetData(int id);
// 支持多数据库操作
[SqlExecute(@"
select * from person;
select * from student;"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]
DataSet GetData();
// 异步方式
[SqlExecute(@"
select * from person;
select * from student;
select 1;"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]
Task<DataSet> GetDataAsync());
}
}
9.18.4.4 返回 Tuple<T1,...T8>
using Furion.DatabaseAccessor;
namespace Furion.Application
{
public interface ISql : ISqlDispatchProxy
{
// 执行sql并传入参数,基元类型
[SqlExecute(@"
select * from person where id >@id and name like @name;
select top 10 * from student where Id >@id;")]
(List<Person>,List<Student>) GetData(int id, string name);
// 执行sql并传入参数,对象类型
[SqlExecute(@"
select * from person where id >@id and name like @name;
select top 10 * from student where Id >@id;")]
(List<Person>,List<Student>) GetData(MyParam paras);
// 执行存储过程 sql,支持设置参数类型
[SqlExecute(@"
exec PROP_NAME @id;
select * from person;", CommandType = CommandType.StoredProcedure)]
(List<Person>,List<Student>) GetData(int id);
// 支持多数据库操作
[SqlExecute(@"
select * from person;
select * from student;"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]
(List<Person>,List<Student>) GetData();
// 异步方式
[SqlExecute(@"
select * from person;
select * from student;
select 1;"), SqlDbContextLocator(typeof(MySqlDbContextLocator)]
Task<(List<Person>,List<Student>,List<int>)> GetDataAsync();
// 自 v3.7.3+ 版本支持返回单个类类型参数
[SqlExecute(@"
select * from person where id =@id;
select * from person")]
(Person, List<Person>) GetData(int id); // 注意返回值是 `(Person, List<Person>)` 组合
}
9.18.4.5 返回 单行单列
using Furion.DatabaseAccessor;
namespace Furion.Application
{
public interface ISql : ISqlDispatchProxy
{
[SqlExecute("select Name from person where id = @id")]
string GetValue(int id);
[SqlExecute("select age from person where id = @id")]
int GetValue(int id);
[SqlExecute("select Name from person where id = @id")]
Task<string> GetValueAsync(int id);
}
}
9.18.4.6 无返回值
using Furion.DatabaseAccessor;
namespace Furion.Application
{
public interface ISql : ISqlDispatchProxy
{
[SqlExecute("insert into person(Name,Age) values(@name,@age)")]
void Insert(MyParam dto);
[SqlExecute("delete from person where id = @id")]
void Delete(int id);
[SqlExecute("update person set name=@name where id=@id")]
void Update(int id, string name);
}
}
9.18.4.7 返回单个类类型参数
版本说明
以下内容仅限 Furion 3.7.1 +
版本使用。
public interface ISql : ISqlDispatchProxy
{
// 自 v3.7.3+ 版本支持返回单个类类型参数
[SqlExecute("select * from person where id=@id")]
Person GetPerson(int id);
}
9.18.4.8 返回受影响行数
版本说明
以下内容仅限 Furion 4.4.5 +
版本使用。
需要在 [SqlExcuete]
特性中标记 RowEffects = true
且返回值是 int
或者 Task<int>
。
public interface ISql : ISqlDispatchProxy
{
// 同步
[SqlExecute("update person set age = 30 where id = {id}", RowEffects = true)]
int Update(int id);
// 异步
[SqlExecute("update person set age = 30 where id = {id}", RowEffects = true)]
Task<int> UpdateAsync(int id);
}