在示例“22-09-28-02_SqlSugarAcquaintance(初识SqlSugarCore之最简注入)”中,数据库连接字符串被直接定义到“上下文”类的构造方法中,但这种实现方式只能用于示例性程序,对于工程程序来说这种实现方式不绝对不被允许的,数据库连接字符串必须定义在JSON类型的文件中,最好定义在“appsettings.json”文件中。
SqlSugarCore中间件中没有内置定义“上下文”类进行依赖注入方法,所以开发者必须自定义“上下文”依赖注入方法,来实现把“上下文”类的实例注入到.Net(Core)6内置容器中,最终达到的效果如下:
//通过UseSqlServer依赖注入中间方法,通过“SQL Server身份认证”对SQL Server数据库进行身份验证,并与SQL Server数据库进行连接,连接字符串中必须配置所连接数据库的:用户名、密码。
builder.Services.AddDbContext<EFCoreContext>
(options => options.UseSqlServer(builder.Configuration.GetConnectionString("SqlServerSQL")));
下面将通过对示例“22-09-28-02_SqlSugarAcquaintance(初识SqlSugarCore之最简注入)”的一步步重构,深入探究怎样使用ConfigureOptions来实现上述效果的自定义的“上下文”依赖注入方法。
1、在“appsettings.json”文件中定义数据连接字符串
"ConnectionStrings": {
//Trusted_Connection=true或Integrated Security=true/SSPI:“Windows凭据”对SQL Server进行身份验证,表示可以在不知道数据库用户名和密码的情况下时,依然可以连接SQL Server数据库。
//"integrated":"security=true是通过“Windows凭据”对SQL Server数据库进行身份验证,并与SQL Server数据库进行连接;表示可以在不知道数据库用户名和密码的情况下时,依然可以连接SQL Server数据库,如果integrated", "security=false","或者不写,表示一定要输入正确的数据库登录名和密码。": null。
//Persist Security Info:该配置只用于通过“SQL Server身份认证”对SQL Server数据库进行身份验证,并与SQL Server数据库进行连接;简单的理解为"ADO在数据库连接成功后是否保存密码信息",True表示保存,False表示不保存.ADO缺省为True(ADO.net缺省为False,未测试,根据参考资料上说的)。
//MultipleActiveResultSets:它允许在单个连接上执行多重的数据库查询或存储过程,目前只适用于Sql Server 2005及其以上版本;如果不用MultipleActiveResultSets ,则一般报错为sqldatareader未关闭,即需要关闭了之后才能打开另一个。
//Trust Server Certificate:是否使用SSL证书和加密方式,对SQL Server数据库的连接字符串进行加密,该操作属于安全性配置,目前只适用于Sql Server 2005及其以上版本;
//"SqlServerWindows":"Data Source=.;Initial Catalog=JsonTable;Integrated Security=true;MultipleActiveResultSets=true;Trust Server Certificate=True",
"SqlServerSQL": "Data Source=.;Initial Catalog=SqlSugarAcquaintance;Integrated Security=False;Persist Security Info=False;User ID=zz;Password=zz;MultipleActiveResultSets=true;Trust Server Certificate=True"
},
2 注入1个“new”配置实例,及其“上下文”实例
2.1 SqlSugarConfigureOption类
using SqlSugar;
namespace Data.Infrastructure.Options
{
/// <summary>
/// 【SqlSugar配置操作】
/// </summary>
/// <remarks>
/// 摘要:
/// 把与数据库软件连接相关的数据,存储到该类的实例中
/// 说明:
/// 无返回回调参数实例(Action<SqlSugarConfigureOption>)执行实例化第3步:在对“上下文”该拷贝构造方法中的参数实例化时,以设定的配置实例,
/// 对该类的已经注入在容器中的默认配置实例(继承于“IConfigureOptions”接口或ConfigureOptions类)进行覆盖。
/// </remarks>
public class SqlSugarConfigureOption
{
/// <summary>
/// 【连接字符串】
/// </summary>
/// <remarks>
/// 摘要:
/// 获取/设置连接字符串,当前程序通过该连接字符串与指定数据库软件中指定数据库进行连接。
/// </remarks>
public string ConnectionString { get; set; }
/// <summary>
/// 【数据类型】
/// </summary>
/// <remarks>
/// 摘要:
/// 获取/设置1个指定的枚举实例,该枚举实例用于指定1个数据库软件,并通过该软件中的指定数据库通过SqlSugarCore中间件与当前程序进行数据交互操作。
/// </remarks>
public DbType DbType { get; set; }
}
}
2.2 为SqlSugarContext类定义1个重载拷贝构造方法
///<param name="options">“SqlSugar配置操作”实例,该参数实例为SqlSugarCore中间件“上下文”类实例的实例化操作提供数据支撑。</param>
/// <summary>
/// 【拷贝构造方法】
/// </summary>
/// <remarks>
/// 摘要:
/// 通过该拷贝构造方法连接到指定数据库(SQL Server)数据库软件中数据库,获取SqlSugarScope实例,实现在数据库软件(SQL Server)中自动生成相应的数据库及其表,
/// 同时为当前项目的实体与数据库中相应表的CURD操作提供支持实例(SqlSugarScope实例)。
/// 说明:
/// 该拷贝构造方法把1个“new”配置实例,及其“上下文”类的实例注入到内置容器中,并通过配置实例,对“上下文”类构造方法中的参数进行实例化。
/// </remarks>
public SqlSugarContext(SqlSugarConfigureOption options)
{
_sqlSugarScope = new SqlSugarScope(new ConnectionConfig()
{
//数据库连接字符串,该字符串特定针对:SqlServer数据库软件。
ConnectionString = options.ConnectionString,
//实现数据交互操作的数据库软件(SqlSugarCore中间件的默认缺省枚举实例为:“MySql”,即MySql数据库软件;当前被设定为:SqlServer数据库软件)。
DbType = options.DbType,
//默认false, 时候知道关闭数据库连接, 设置为true,即自动释放数据库,如果存在事务,在事务结束后释放,而无需使用using块或者Close内置方法定义释放操作。
IsAutoCloseConnection = true,
//默认SystemTable, 字段信息读取, 如:该属性是不是主键,标识列等等信息,即从实体特性中读取主键自增列信息。
InitKeyType = InitKeyType.Attribute
});
//在指定数据库(SQL Server)数据库软件中自动生成相应的数据库及其表。
CreateTable(false, 50, typeof(Specialty));
}
2.3 ServiceCollectionExtensions. AddSqlSugar注入方法
using Data;
using Data.Infrastructure.Options;
using Microsoft.Extensions.Options;
namespace Web.Infrastructure.Extensions
{
/// <summary>
/// 【依赖注入扩展】
/// </summary>
/// <remarks>
/// 摘要:
/// 通过该类把配置实例,及其“上下文”类的实例注入到内置容器中。
/// </remarks>
public static class ServiceCollectionExtensions
{
///<param name="services">.Net(Core)框架内置依赖注入容器实例。</param>
///<param name="options">“SqlSugar配置操作”实例,该参数实例为SqlSugarCore中间件“上下文”类实例的实例化操作提供数据支撑。</param>
/// <summary>
/// 【SqlSugar注入】
/// </summary>
/// <remarks>
/// 摘要:
/// 该方法用于把1个“new”配置实例,注入到内置容器中;并声明了“上下文”类的注入操作。
/// </remarks>
public static void AddSqlSugar(this IServiceCollection services, SqlSugarConfigureOption options)
{
//通过下行语句的注入操作,可以很明显的得出:
//1、容器中被注入的是:类的实例。
//2、拷贝构造方法中的接口或类的参数,及其GetService<T>()等的作用是:通过指定,来从容器中拿到与之相对应的1个或多个(接口注入)实例。
//3、器容器中实例的生命周期,由:AddSingleton、AddScoped和AddTransient这3个内置注入方法所实现和决定。
//4、ServiceProvider?.GetService<T>()等,由“?”所设定的语法糖操作,进一步佐证了容器中存储的是:类的实例。
//5、“?”语法糖实质上是“== null”,而“null”所对应的就是“object”, 而“object”就是实例对象。
//6、其实所有的自定义注方法都是静态的,从这方法也可以间接得出容器中存储的是:类的实例。
services.AddSingleton(options);
//声明通过“AddSingleton”方法,用于确认“上下文”类的实例,是需要被注入到内置容器中的(当前容器中并没有“上下文”类的实例),并同时声明了该实例的生命周期,
//在程序运行时,已经实例化的配置实例作为“上下文”拷贝构造方法的中参数值,来对“上下文”类时行实例化进行支撑的同时,把“上下文”类的实例注入到内置容器中。
services.AddSingleton<SqlSugarContext>();
}
}
}
2.4 Program.cs把1个“new”配置实例,及其“上下文”类的实例注入到内置容器中
//把“new”1个配置实例,及其“上下文”类的实例注入到内置容器中,并通过配置实例,对“上下文”类构造方法中的参数及其“上下文”类本身进行实例化。
//注意:使用该依赖注入方法时,必把“SqlSugarContext(IOptions<SqlSugarConfigureOption> options)”方法的定义注释掉否则会出现异常。
builder.Services.AddSqlSugar(
new SqlSugarConfigureOption
{
ConnectionString = builder.Configuration.GetConnectionString("SqlServerSQL"),
DbType = DbType.SqlServer
});
按F5执行程序后SQL Server 数据库软件中会自动生成相应的数据库。
3 注入1个“IConfigureOptions”配置实例,及其“上下文”实例
3.1 SqlSugarIConfigure类
注意:在定义前必须先在“Data”项目中通过“Nuget”引用中间件:“Microsoft.AspNetCore.Mvc.NewtonsoftJson”
using Microsoft.Extensions.Options;
using SqlSugar;
namespace Data.Infrastructure.Options
{
/// <summary>
/// 【SqlSugar配置操作】
/// </summary>
/// <remarks>
/// 摘要:
/// 通过该类通过对所继承“IConfigureOptions”接口方法的实现,初始化设定了定义在“IConfigureOptions”中的“TOptions”范型参数实例的默认值。
/// 说明:
/// 无返回回调参数实例(Action<SqlSugarConfigureOption>)执行实例化第1步:通过把已经注入到容器中的配置实例设定值,覆盖当前类中定义的配置实例的默认值。
/// </remarks>
public class SqlSugarIConfigure : IConfigureOptions<SqlSugarConfigureOption>
{
#region 方法--接口实现
///<param name="options">“SqlSugar配置操作”实例,该参数实例为SqlSugarCore中间件“上下文”类实例的实例化操作提供数据支撑。</param>
/// <summary>
/// 【配置】
/// </summary>
/// <remarks>
/// 摘要:
/// 对所继承“IConfigureOptions”接口方法的实现,初始化设定了定义在“IConfigureOptions”中的“TOptions”范型参数实例的默认值。
/// </remarks>
public void Configure(SqlSugarConfigureOption options)
{
options.ConnectionString = String.Empty;
options.DbType = DbType.SqlServer;
}
#endregion
}
}
3.2为SqlSugarContext类定义1个重载拷贝构造方法
///<param name="options">“SqlSugar配置操作”实例,该参数实例为SqlSugarCore中间件“上下文”类实例的实例化操作提供数据支撑。</param>
/// <summary>
/// 【拷贝构造方法】
/// </summary>
/// <remarks>
/// 摘要:
/// 通过该拷贝构造方法连接到指定数据库(SQL Server)数据库软件中数据库,获取SqlSugarScope实例,实现在数据库软件(SQL Server)中自动生成相应的数据库及其表,
/// 同时为当前项目的实体与数据库中相应表的CURD操作提供支持实例(SqlSugarScope实例)。
/// 说明:
/// 1、该拷贝构造方法把1个继承于“IConfigureOptions”接口或ConfigureOptions类的配置实例,及其“上下文”类的实例注入到内置容器中,
/// 并通过配置实例,对“上下文”类构造方法中的参数及其“上下文”类本身进行实例化。
/// 2、 无返回回调参数实例(Action<SqlSugarConfigureOption>)执行实例化第2步:通过覆盖后的配置实例,实例化该拷贝构造方法中的参数。
/// </remarks>
public SqlSugarContext(IOptions<SqlSugarConfigureOption> options)
{
//无返回回调参数实例(Action<SqlSugarConfigureOption>)执行实例化第4步:通过该拷贝构造方法中的被覆盖后的参数实例,为“_sqlSugarScope”实例化提供数据支持。
_sqlSugarScope = new SqlSugarScope(new ConnectionConfig()
{
//数据库连接字符串,该字符串特定针对:SqlServer数据库软件。
ConnectionString = options.Value.ConnectionString,
//实现数据交互操作的数据库软件(SqlSugarCore中间件的默认缺省枚举实例为:“MySql”,即MySql数据库软件;当前被设定为:SqlServer数据库软件)。
DbType = options.Value.DbType,
//默认false, 时候知道关闭数据库连接, 设置为true,即自动释放数据库,如果存在事务,在事务结束后释放,而无需使用using块或者Close内置方法定义释放操作。
IsAutoCloseConnection = true,
//默认SystemTable, 字段信息读取, 如:该属性是不是主键,标识列等等信息,即从实体特性中读取主键自增列信息。
InitKeyType = InitKeyType.Attribute
});
//在指定数据库(SQL Server)数据库软件中自动生成相应的数据库及其表。
CreateTable(false, 50, typeof(Specialty));
}
3.3 ServiceCollectionExtensions.AddSqlSugarIConfigureOption注入方法
///<param name="services">.Net(Core)框架内置依赖注入容器实例。</param>
///<param name="configure">无返回委托方法参数实例,该参数实例为SqlSugarCore中间件“上下文”类实例的实例化操作提供数据支撑。</param>
/// <summary>
/// 【SqlSugar注入】
/// </summary>
/// <remarks>
/// 摘要:
/// 该方法用于把1个1个继承于“IConfigureOptions”接口注入配置实例,及其“上下文”类的实例注入到内置容器中。
/// </remarks>
public static void AddSqlSugarIConfigureOption(this IServiceCollection services, Action<SqlSugarConfigureOption> configure)
{
//声明通过“AddSingleton”方法,用于确认“上下文”类的实例,是需要被注入到内置容器中的(当前容器中并没有“上下文”类的实例),并同时声明了该实例的生命周期,
//在程序运行时,已经实例化的配置实例作为“上下文”拷贝构造方法的中参数值,来对“上下文”类时行实例化的同时,注入到内置容器中。
services.AddSingleton<SqlSugarContext>();
//通过“SqlSugarIConfigure”类所设定的默认实例,对定义在“IConfigureOptions”中的“TOptions”范型参数进行实例化。
services.AddSingleton<IConfigureOptions<SqlSugarConfigureOption>, SqlSugarIConfigure>();
//把无返回委托方法参数实例,注入到到内置容器中,当程序main方法运行结束后,通过该委托方法的回调操作,
//用设定配置实例覆盖默认配置实例,从而实现把“上下文”类时行实例化的同时,注入到内置容器中。
if (configure != null)
{
services.Configure(configure);
}
}
3.4 Program.cs把1个“IConfigureOptions”配置实例,及其“上下文”类的实例注入到内置容器中
//把“IConfigureOptions”1个配置实例,及其“上下文”类的实例注入到内置容器中,并通过配置实例,对“上下文”类构造方法中的参数及其“上下文”类本身进行实例化。
builder.Services.AddSqlSugarIConfigureOption(
optitons =>
{
optitons.ConnectionString = builder.Configuration.GetConnectionString("SqlServerSQL");
});
按F5执行程序后SQL Server 数据库软件中会自动生成相应的数据库。
4 注入1个“ConfigureOptions”配置实例,及其“上下文”实例
4.1 SqlSugarConfigure类
using Data.Infrastructure.Options;
using Microsoft.Extensions.Options;
using SqlSugar;
namespace Data.Options
{
/// <summary>
/// 【SqlSugar配置操作】
/// </summary>
/// <remarks>
/// 摘要:
/// 通过该类通过对所继承“ConfigureOptions”方法的实现,初始化设定了定义在“IConfigureOptions”中的“TOptions”范型参数实例的默认值。
/// 说明:
/// 无返回回调参数实例(Action<SqlSugarConfigureOption>)执行实例化第1步:通过把已经注入到容器中的配置实例设定值,覆盖当前类中定义的配置实例的默认值。
/// </remarks>
public class SqlSugarConfigure : ConfigureOptions<SqlSugarConfigureOption>
{
#region 拷贝构造方法与依赖注入变量实例化
/// <summary>
/// 【拷贝构造方法】
/// </summary>
/// <remarks>
/// 摘要:
/// 通过该拷贝构造方法,在无返回回调参数实例执行是通过其基类的拷贝构造方法,把已经注入到容器中的配置实例设定值,覆盖当前类中定义的配置实例的默认值。
/// 说明:
/// 强制类型转换定义“(Action<SqlSugarConfigureOption>)”可以直接删除掉,但为了突出显示“无返回回调参数实例”没有删除。
/// </remarks>
public SqlSugarConfigure() : base((Action<SqlSugarConfigureOption>)ConfigureSqlSugarOption)
{
}
#endregion
#region 方法--接口实现
///<param name="options">“SqlSugar配置操作”实例,该参数实例为SqlSugarCore中间件“上下文”类实例的实例化操作提供数据支撑。</param>
/// <summary>
/// 【配置“上下文”类实例】
/// </summary>
/// <remarks>
/// 摘要:
/// 通过该无返回回调静态构建方法参数实例,基类的拷贝构造方法,初始化设定了定义在“IConfigureOptions”中的“TOptions”范型参数实例的默认值。
/// 说明:
/// 通过该该无返回回调静态构建方法,可以很显的得出默认配置实例,是在“main”方法运行前就被注入到了内置容器中。
/// </remarks>
public static void ConfigureSqlSugarOption(SqlSugarConfigureOption options)
{
}
#endregion
#region 方法--覆写
///<param name="options">“SqlSugar配置操作”实例,该参数实例为SqlSugarCore中间件“上下文”类实例的实例化操作提供数据支撑。</param>
/// <summary>
/// 【SqlSugar注入】
/// </summary>
/// <remarks>
/// 摘要:
/// 对所继承“IConfigureOptions”接口方法的实现,初始化设定了定义在“IConfigureOptions”中的“TOptions”范型参数实例的默认值。
/// </remarks>
public override void Configure(SqlSugarConfigureOption options)
{
if (options == null)
{
throw new ArgumentNullException("options");
}
options.ConnectionString = string.Empty;
options.DbType = DbType.SqlServer;
base.Configure(options);
}
#endregion
}
}
4.2 ServiceCollectionExtensions.AddSqlSugarConfigureOption注入方法
///<param name="services">.Net(Core)框架内置依赖注入容器实例。</param>
///<param name="configure">无返回委托方法参数实例,该参数实例为SqlSugarCore中间件“上下文”类实例的实例化操作提供数据支撑。</param>
/// <summary>
/// 【SqlSugar注入】
/// </summary>
/// <remarks>
/// 摘要:
/// 该方法用于把1个1个继承于“ConfigureOptions”注入配置实例,及其“上下文”类的实例注入到内置容器中。
/// </remarks>
public static void AddSqlSugarConfigureOption(this IServiceCollection services, Action<SqlSugarConfigureOption> configure)
{
//声明通过“AddSingleton”方法,用于确认“上下文”类的实例,是需要被注入到内置容器中的(当前容器中并没有“上下文”类的实例),并同时声明了该实例的生命周期,
//在程序运行时,已经实例化的配置实例作为“上下文”拷贝构造方法的中参数值,来对“上下文”类时行实例化的同时,注入到内置容器中。
services.AddSingleton<SqlSugarContext>();
//通过“SqlSugarConfigure”类所设定的默认实例,对定义在“IConfigureOptions”中的“TOptions”范型参数进行实例化。
services.AddSingleton<IConfigureOptions<SqlSugarConfigureOption>, SqlSugarConfigure>();
//把无返回委托方法参数实例,注入到到内置容器中,当程序main方法运行结束后,通过该委托方法的回调操作,
//用设定配置实例覆盖默认配置实例,从而实现把“上下文”类时行实例化的同时,注入到内置容器中。
if (configure != null)
{
services.Configure(configure);
}
}
4.3 Program.cs注入定义的最终形态
var builder = WebApplication.CreateBuilder(args);
//以最简注入方式,并对“上下文”类构造方法进行实例化。
//builder.Services.AddSingleton<SqlSugarContext>();
//把“new”1个配置实例,及其“上下文”类的实例注入到内置容器中,并通过配置实例,对“上下文”类构造方法中的参数及其“上下文”类本身进行实例化。
//注意:使用该依赖注入方法时,必把“SqlSugarContext(IOptions<SqlSugarConfigureOption> options)”方法的定义注释掉否则会出现异常。
//builder.Services.AddSqlSugar(
// new SqlSugarConfigureOption
// {
// ConnectionString = builder.Configuration.GetConnectionString("SqlServerSQL"),
// DbType = DbType.SqlServer
// });
//把“IConfigureOptions”1个配置实例,及其“上下文”类的实例注入到内置容器中,并通过配置实例,对“上下文”类构造方法中的参数及其“上下文”类本身进行实例化。
//builder.Services.AddSqlSugarIConfigureOption(
// optitons =>
// {
// optitons.ConnectionString = builder.Configuration.GetConnectionString("SqlServerSQL");
// });
//把“ConfigureOptions”1个配置实例,及其“上下文”类的实例注入到内置容器中,并通过配置实例,对“上下文”类构造方法中的参数及其“上下文”类本身进行实例化。
builder.Services.AddSqlSugarConfigureOption(
optitons =>
{
optitons.ConnectionString = builder.Configuration.GetConnectionString("SqlServerSQL");
});
// Add services to the container.
builder.Services.AddControllersWithViews();
var app = builder.Build();
按F5执行程序后SQL Server 数据库软件中会自动生成相应的数据库。
对以上功能更为具体实现和注释见:22-09-29-03_SqlSugarAcquaintance(初识SqlSugarCore之ConfigureOptions注入实现)。