1 为什么使用Microsoft.Data.SqlClient中间件实现CURD操作
1、数据库的生成是通过“Microsoft.Data.SqlClient”中间件。
2、数据库中表生成是通过“EntityFrameworkCore”中间件。
3、实际上数据库数据库及其表的生成可以不使用“Microsoft.Data.SqlClient”中间件,可以通过“EntityFrameworkCore”中间件来直接自动生成数据库数据库及其表。
4、由于“EntityFrameworkCore”中间件封装太严密,使用“Microsoft.Data.SqlClient”中间件的最根本目的是可以使用最底层的方法来实现对数据的操作。
5、在实际开发中第3方日志中间件(NLog/Log4net)与数据库的写入操作,也是通过“Microsoft.Data.SqlClient”中间件来实现的;读取操作则是通过“EntityFrameworkCore”中间件来完成。
6、“Microsoft.Data.SqlClient”中间件可以以更加灵活的方式来实现当前程序对多数据库软件的支撑。
7、为了简化程序的中的CRUD实现,可以把程序中与“Microsoft.Data.SqlClient”中间件相关的定义全部删除,因为通过“EntityFrameworkCore”中间件实现同样的功能,只是不如“Microsoft.Data.SqlClient”中间件底层和灵活吧了。
8、如果EntityFrameworkCore/SqlSugar/FluentMigrator中间件对一些数据库软件中的数据库的CURD操作不能完全支持,就需要“Microsoft.Data.SqlClient”或“LinqToDB”中间件进行配合了。
2 Data.DataProvider.IDataProviderManager
namespace Data.DataProvider
{
/// <summary>
/// 【数据库软件提供程序管理器--接口】
/// <remarks>
/// 摘要:
/// 继承于该接口的具体实现类中的成员获取数据库软件提供程序接口实例,该实例用于通过“Microsoft.Data.SqlClient”中间件实现当前程序与1个指定数据软件中1个指定数据库的CURD操作。
/// </remarks>
/// </summary>
public interface IDataProviderManager
{
#region 属性
/// <summary>
/// 【数据库软件提供程序】
/// <remarks>
/// 摘要:
/// 数据库软件提供程序接口实例,该实例用于通过“Microsoft.Data.SqlClient”中间件实现当前程序与1个指定数据软件中1个指定数据库的CURD操作。
/// </remarks>
/// </summary>
IDataProvider DataProvider { get; }
#endregion
}
}
3 Data.DataProvider.DataProviderManager
using Core;
using Core.Infrastructure;
using Data.Configuration;
namespace Data.DataProvider
{
/// <summary>
/// 【数据库软件提供程序管理器--类】
/// <remarks>
/// 摘要:
/// 通过该类中的成员获取数据库软件提供程序接口实例,该实例用于通过“Microsoft.Data.SqlClient”中间件实现当前程序与1个指定数据软件中1个指定数据库的CURD操作。
/// </remarks>
/// </summary>
public class DataProviderManager : IDataProviderManager
{
#region 属性
/// <summary>
/// 【数据库软件提供程序】
/// <remarks>
/// 摘要:
/// 数据库软件提供程序接口实例,该实例用于通过“Microsoft.Data.SqlClient”中间件实现当前程序与1个指定数据软件中1个指定数据库的CURD操作。
/// </remarks>
/// </summary>
public IDataProvider DataProvider
{
get
{
var dataProviderType = Singleton<DataConfig>.Instance.DataProvider;
return GetDataProvider(dataProviderType);
}
}
#endregion
#region 方法
/// <param name="dataProviderType">数据库软件类型提供程序枚举的1个指定实例。</param>
/// <summary>
/// 【获取数据库软件提供程序】
/// <remarks>
/// 摘要:
/// 获取数据库软件提供程序接口实例,该实例用于通过“Microsoft.Data.SqlClient”中间件实现当前程序与1个指定数据软件中1个指定数据库的CURD操作。
/// </remarks>
/// <returns>
/// 返回:
/// 数据库软件提供程序接口实例,该实例用于通过“Microsoft.Data.SqlClient”中间件实现当前程序与1个指定数据软件中1个指定数据库的CURD操作。
/// </returns>
/// </summary>
public static IDataProvider GetDataProvider(DataProviderType dataProviderType)
{
return dataProviderType switch
{
DataProviderType.SqlServer => new SqlServerDataProvider(),
DataProviderType.MySql => new MySqlDataProvider(),
_ => throw new NopException($"数据库软件类型提供程序枚举中没有定义: '{dataProviderType}'枚举成员。"),
};
}
#endregion
}
}
4 Data.DataProvider.IDataProvider
namespace Data.DataProvider
{
/// <summary>
/// 【数据库提供程序--接口】
/// <remarks>
/// 摘要:
/// 通过继承于该接口的具体实现类中的方法成员,实现程序通过“Microsoft.Data.SqlClient”中间件与1个指定数据库软件中1个指定数据库的CURD操作。
/// </remarks>
/// </summary>
public interface IDataProvider
{
#region 方法
/// <summary>
/// 【异步数据库存在?】
/// <remarks>
/// 摘要:
/// 获取1个值false(不存在)/true(存在),该值指定是否可以通过“Microsoft.Data.SqlClient”中间件的异步打开操作,来验证1个指定的数据库软件中是否存在1个指定数据库。
/// </remarks>
/// <returns>
/// 返回:
/// 1个值false(不存在)/true(存在)。
/// </returns>
/// </summary>
Task<bool> DatabaseExistsAsync();
/// <summary>
/// 【数据库存在?】
/// <remarks>
/// 摘要:
/// 获取1个值false(不存在)/true(存在),该值指定是否可以通过“Microsoft.Data.SqlClient”中间件的打开操作,来验证1个指定的数据库软件中是否存在1个指定数据库。
/// </remarks>
/// <returns>
/// 返回:
/// 1个值false(不存在)/true(存在)。
/// </returns>
/// </summary>
bool DatabaseExists();
/// <param name="collation">
/// 在多语言环境下,数据库新建/声明操作中,通过该选定的服务器级别的字符串名称,可以在显示本地化值是,可以按照本地的排序顺序进行显示,
/// 同时防止本地字符值以乱码进行显示,但随着数据库版本的改进,即使用不对该参数进行实例化,也不会造成前面所述的现象的产生,但是保留该参数,
/// 在特定的数据库软件中说不定能够使用到。
/// </param>
/// <param name="triesToConnect">设置10秒钟延迟(默认值:10*1秒)的延迟,以确保在1个指定的数据库软件中新建1个指定的数据库;如果不需要延迟,也可以把该参数的值设置为:0。</param>
/// <summary>
/// 【新建数据库】
/// <remarks>
/// 摘要:
/// 通过“Microsoft.Data.SqlClient”中间件在1个指定的数据库软件中新建1个指定的数据库。
/// </remarks>
/// </summary>
void CreateDatabase(string collation, int triesToConnect = 10);
#endregion
}
}
5 Data.DataProvider.BaseDataProvider
using Data.Configuration;
using System.Data.Common;
namespace Data.DataProvider
{
/// <summary>
/// 【数据提供程序基类--类】
/// <remarks>
/// 摘要:
/// 通过该类中的方法成员实现程序通过“Microsoft.Data.SqlClient”中间件与1个指定数据库软件中1个指定数据库的CURD操作。
/// </remarks>
/// </summary>
public abstract class BaseDataProvider
{
#region 方法--私有/保护
/// <param name="connectionString"> 1个指定数据库软件中1个指定数据库的连接字符串。</param>
/// <summary>
/// 【获取内置数据库连接】
/// <remarks>
/// 摘要:
/// 获取“Microsoft.Data.SqlClient”中间件的数据连接实例,该实例用于在1个指定的数据库软件中新建、打开、关闭指定的数据库等操作。
/// </remarks>
/// <returns>
/// 返回:
/// 数据连接实例,该实例用于通过“Microsoft.Data.SqlClient”中间件在1个指定的数据库软件中新建、打开、关闭指定的数据库等操作。
/// </returns>
/// </summary>
protected abstract DbConnection GetInternalDbConnection(string connectionString);
/// <summary>
/// 【获取当前字符连接字符串】
/// <remarks>
/// 摘要:
/// 从单例实例的变量和属性字典成员实例中获取1个指定数据库软件中1个指定数据库的连接字符串。
/// </remarks>
/// <returns>
/// </returns>
/// </summary>
protected static string GetCurrentConnectionString()
{
return DataSettingsManager.LoadSettings().ConnectionString;
}
/// <param name="connectionString"> 1个指定数据库软件中1个指定数据库的连接字符串。</param>
/// <summary>
/// 【获取内置数据库连接】
/// <remarks>
/// 摘要:
/// 获取“Microsoft.Data.SqlClient”中间件的数据连接实例,该实例用于在“MySql”数据库软件中新建、打开、关闭指定的数据库等操作。
/// </remarks>
/// <returns>
/// 返回:
/// 数据连接实例,该实例用于通过“Microsoft.Data.SqlClient”中间件在“MySql”数据库软件中新建、打开、关闭指定的数据库等操作。
/// </returns>
/// </summary>
protected virtual DbConnection CreateDbConnection(string connectionString = null)
{
var dbConnection = GetInternalDbConnection(!string.IsNullOrEmpty(connectionString) ? connectionString : GetCurrentConnectionString());
//return MiniProfillerEnabled ? new ProfiledDbConnection(dbConnection, MiniProfiler.Current) : dbConnection;
return dbConnection;
}
#endregion
}
}
6 Data.DataProvider.SqlServerDataProvider
using Data.Configuration;
using Microsoft.Data.SqlClient;
using System.Data.Common;
namespace Data.DataProvider
{
/// <summary>
/// 【MS数据提供程序--类】
/// <remarks>
/// 摘要:
/// 通过该类中的方法成员实现程序通过“Microsoft.Data.SqlClient”中间件与“Microsoft SQL Server”数据库软件中1个指定数据库的CURD操作。
/// </remarks>
/// </summary>
public class SqlServerDataProvider : BaseDataProvider, IDataProvider
{
#region 方法--私有/保护--基类抽象实现
/// <param name="connectionString"> 1个指定数据库软件中1个指定数据库的连接字符串。</param>
/// <summary>
/// 【获取内置数据库连接】
/// <remarks>
/// 摘要:
/// 获取“Microsoft.Data.SqlClient”中间件的数据连接实例,该实例用于在“Microsoft SQL Server”数据库软件中新建、打开、关闭指定的数据库等操作。
/// </remarks>
/// <returns>
/// 返回:
/// 数据连接实例,该实例用于通过“Microsoft.Data.SqlClient”中间件在“Microsoft SQL Server”数据库软件中新建、打开、关闭指定的数据库等操作。
/// </returns>
/// </summary>
protected override DbConnection GetInternalDbConnection(string connectionString)
{
if (string.IsNullOrEmpty(connectionString))
throw new ArgumentNullException(nameof(connectionString));
//获取数据连接实例,该实例用于通过“Microsoft.Data.SqlClient”中间件在指定的数据库软件中新建、打开、关闭指定的数据库等操作。
return new SqlConnection(connectionString);
}
#endregion
#region 方法--私有/保护
/// <summary>
/// 【获取数据库连接字符串构建】
/// <remarks>
/// 摘要:
/// 通过“Microsoft.Data.SqlClient”中间件获取“Microsoft SQL Server”数据库软件的数据库连接字符串构建实例,该实例用于对数据库连接字符串进行数据库名、用户名、密码等配置修改、新建等操作。
/// </remarks>
/// <returns>
/// 返回:
/// “Microsoft SQL Server”数据库软件的数据库连接字符串构建实例,该实例用于对数据库连接字符串进行数据库名、用户名、密码等配置修改、新建等操作。
/// </returns>
/// </summary>
protected virtual SqlConnectionStringBuilder GetConnectionStringBuilder()
{
var connectionString = DataSettingsManager.LoadSettings().ConnectionString;
return new SqlConnectionStringBuilder(connectionString);
}
#endregion
#region 方法--接口实现
/// <summary>
/// 【异步数据库存在?】
/// <remarks>
/// 摘要:
/// 获取1个值false(不存在)/true(存在),该值指定是否可以通过“Microsoft.Data.SqlClient”中间件的异步打开操作,来验证“Microsoft SQL Server”数据库软件中是否存在1个指定数据库。
/// </remarks>
/// <returns>
/// 返回:
/// 1个值false(不存在)/true(存在)。
/// </returns>
/// </summary>
public async Task<bool> DatabaseExistsAsync()
{
try
{
await using var connection = GetInternalDbConnection(GetCurrentConnectionString());
//通过“Microsoft.Data.SqlClient”中间件的异步打开操作,来验证“Microsoft SQL Server”数据库软件中是否存在1个指定数据库。
await connection.OpenAsync();
return true;
}
catch
{
return false;
}
}
/// <summary>
/// 【数据库存在?】
/// <remarks>
/// 摘要:
/// 获取1个值false(不存在)/true(存在),该值指定是否可以通过“Microsoft.Data.SqlClient”中间件的打开操作,来验证“Microsoft SQL Server”数据库软件中是否存在1个指定数据库。
/// </remarks>
/// <returns>
/// 返回:
/// 1个值false(不存在)/true(存在)。
/// </returns>
/// </summary>
public bool DatabaseExists()
{
try
{
using var connection = GetInternalDbConnection(GetCurrentConnectionString());
//通过“Microsoft.Data.SqlClient”中间件的打开操作,来验证“Microsoft SQL Server”数据库软件中是否存在1个指定数据库。
connection.Open();
return true;
}
catch
{
return false;
}
}
/// <param name="collation">
/// 在多语言环境下,数据库新建/声明操作中,通过该选定的服务器级别的字符串名称,可以在显示本地化值是,可以按照本地的排序顺序进行显示,
/// 同时防止本地字符值以乱码进行显示,但随着数据库版本的改进,即使用不对该参数进行实例化,也不会造成前面所述的现象的产生,但是保留该参数,
/// 在特定的数据库软件中说不定能够使用到。
/// </param>
/// <param name="triesToConnect">设置10秒钟延迟(默认值:10*1秒)的延迟,以确保在“Microsoft SQL Server”数据库软件中新建1个指定的数据库;如果不需要延迟,也可以把该参数的值设置为:0。</param>
/// <summary>
/// 【新建数据库】
/// <remarks>
/// 摘要:
/// 通过“Microsoft.Data.SqlClient”中间件在“Microsoft SQL Server”数据库软件中新建1个指定的数据库。
/// </remarks>
/// </summary>
public void CreateDatabase(string collation, int triesToConnect = 10)
{
//如果能够通过“Microsoft.Data.SqlClient”中间件在“Microsoft SQL Server”数据库软件中打开1个指定的数据库,则直接退出当前方法。
if (DatabaseExists())
return;
//获取数据库连接字符串构建实例。
var builder = GetConnectionStringBuilder();
//通过取数据库连接字符串构建实例,获取指定的数据库名
var databaseName = builder.InitialCatalog;
//新建当前程序与“Microsoft SQL Server”数据库软件中“master”系统数据库的连接。
builder.InitialCatalog = "master";
//通过“Microsoft.Data.SqlClient”中间件的数据连接实例(SqlConnection),在“Microsoft SQL Server”数据库软件中新建1个指定的数据库。
using (var connection = GetInternalDbConnection(builder.ConnectionString))
{
var query = $"CREATE DATABASE [{databaseName}]";
if (!string.IsNullOrWhiteSpace(collation))
query = $"{query} COLLATE {collation}";
var command = connection.CreateCommand();
command.CommandText = query;
command.Connection!.Open();
command.ExecuteNonQuery();
}
//如果延迟参数值被设定为:0,则直接退出当前方法。
if (triesToConnect <= 0)
return;
//有时在慢速服务器(主机)上,通过延迟操作可以确保在“Microsoft SQL Server”数据库软件中新建1个指定的数据库。
for (var i = 0; i <= triesToConnect; i++)
{
if (i == triesToConnect)
throw new Exception("未在“Microsoft SQL Server”数据库软件中新建1个指定的数据库,请把延迟参数值设定为更长的时间。");
//如果不能够通过“Microsoft.Data.SqlClient”中间件在“Microsoft SQL Server”数据库软件中打开1个指定的数据库,则继续延迟;如果能够则直接退出当前方法。
if (!DatabaseExists())
Thread.Sleep(1000);
else
break;
}
}
#endregion
}
}
7 Data.DataProvider.MySqlDataProvider
using MySqlConnector;
using System.Data.Common;
namespace Data.DataProvider
{
/// <summary>
/// 【MySql数据提供程序--类】
/// <remarks>
/// 摘要:
/// 通过该类中的方法成员实现程序通过“Microsoft.Data.SqlClient”中间件与“MySql”数据库软件中1个指定数据库的CURD操作。
/// </remarks>
/// </summary>
public class MySqlDataProvider : BaseDataProvider, IDataProvider
{
#region 方法--私有/保护--基类抽象实现
/// <param name="connectionString"> 1个指定数据库软件中1个指定数据库的连接字符串。</param>
/// <summary>
/// 【获取内置数据库连接】
/// <remarks>
/// 摘要:
/// 获取“Microsoft.Data.SqlClient”中间件的数据连接实例,该实例用于在“MySql”数据库软件中新建、打开、关闭指定的数据库等操作。
/// </remarks>
/// <returns>
/// 返回:
/// 数据连接实例,该实例用于通过“Microsoft.Data.SqlClient”中间件在“MySql”数据库软件中新建、打开、关闭指定的数据库等操作。
/// </returns>
/// </summary>
protected override DbConnection GetInternalDbConnection(string connectionString)
{
if (string.IsNullOrEmpty(connectionString))
throw new ArgumentNullException(nameof(connectionString));
return new MySqlConnection(connectionString);
}
#endregion
#region 方法--私有/保护
/// <summary>
/// 【获取数据库连接字符串构建】
/// <remarks>
/// 摘要:
/// 通过“Microsoft.Data.SqlClient”中间件获取“MySql”数据库软件的数据库连接字符串构建实例,该实例用于对数据库连接字符串进行数据库名、用户名、密码等配置修改、新建等操作。
/// </remarks>
/// <returns>
/// 返回:
/// “MySql”数据库软件的数据库连接字符串构建实例,该实例用于对数据库连接字符串进行数据库名、用户名、密码等配置修改、新建等操作。
/// </returns>
/// </summary>
protected static MySqlConnectionStringBuilder GetConnectionStringBuilder()
{
return new MySqlConnectionStringBuilder(GetCurrentConnectionString());
}
#endregion
#region 方法--接口实现
/// <summary>
/// 【异步数据库存在?】
/// <remarks>
/// 摘要:
/// 获取1个值false(不存在)/true(存在),该值指定是否可以通过“Microsoft.Data.SqlClient”中间件的异步打开操作,来验证“MySql”数据库软件中是否存在1个指定数据库。
/// </remarks>
/// <returns>
/// 返回:
/// 1个值false(不存在)/true(存在)。
/// </returns>
/// </summary>
public async Task<bool> DatabaseExistsAsync()
{
try
{
await using var connection = GetInternalDbConnection(GetCurrentConnectionString());
//通过“Microsoft.Data.SqlClient”中间件的异步打开操作,来验证“MySql”数据库软件中是否存在1个指定数据库。
await connection.OpenAsync();
return true;
}
catch
{
return false;
}
}
/// <summary>
/// 【数据库存在?】
/// <remarks>
/// 摘要:
/// 获取1个值false(不存在)/true(存在),该值指定是否可以通过“Microsoft.Data.SqlClient”中间件的打开操作,来验证“MySql”数据库软件中是否存在1个指定数据库。
/// </remarks>
/// <returns>
/// 返回:
/// 1个值false(不存在)/true(存在)。
/// </returns>
/// </summary>
public bool DatabaseExists()
{
try
{
using var connection = CreateDbConnection();
//通过“Microsoft.Data.SqlClient”中间件的打开操作,来验证“MySql”数据库软件中是否存在1个指定数据库。
connection.Open();
return true;
}
catch
{
return false;
}
}
/// <param name="collation">
/// 在多语言环境下,数据库新建/声明操作中,通过该选定的服务器级别的字符串名称,可以在显示本地化值是,可以按照本地的排序顺序进行显示,
/// 同时防止本地字符值以乱码进行显示,但随着数据库版本的改进,即使用不对该参数进行实例化,也不会造成前面所述的现象的产生,但是保留该参数,
/// 在特定的数据库软件中说不定能够使用到。
/// </param>
/// <param name="triesToConnect">设置10秒钟延迟(默认值:10*1秒)的延迟,以确保在“MySql”数据库软件中新建1个指定的数据库;如果不需要延迟,也可以把该参数的值设置为:0。</param>
/// <summary>
/// 【新建数据库】
/// <remarks>
/// 摘要:
/// 通过“Microsoft.Data.SqlClient”中间件在“MySql”数据库软件中新建1个指定的数据库。
/// </remarks>
/// </summary>
public void CreateDatabase(string collation, int triesToConnect = 10)
{
if (DatabaseExists())
return;
var builder = GetConnectionStringBuilder();
//通过取数据库连接字符串构建实例,获取指定的数据库名。
var databaseName = builder.Database;
//声明当前程序与“MySql”数据库软件的连接实例。
builder.Database = null;
//通过“Microsoft.Data.SqlClient”中间件的数据连接实例(SqlConnection),在“MySql”数据库软件中新建1个指定的数据库。
using (var connection = GetInternalDbConnection(builder.ConnectionString))
{
var query = $"CREATE DATABASE IF NOT EXISTS {databaseName}";
if (!string.IsNullOrWhiteSpace(collation))
query = $"{query} COLLATE {collation}";
var command = connection.CreateCommand();
command.CommandText = query;
command.Connection!.Open();
command.ExecuteNonQuery();
}
//如果延迟参数值被设定为:0,则直接退出当前方法。
if (triesToConnect <= 0)
return;
//有时在慢速服务器(主机)上,通过延迟操作可以确保在“MySql”数据库软件中新建1个指定的数据库。
for (var i = 0; i <= triesToConnect; i++)
{
if (i == triesToConnect)
throw new Exception("未在“MySql”数据库软件中新建1个指定的数据库,请把延迟参数值设定为更长的时间。");
if (!DatabaseExists())
Thread.Sleep(1000);
else
break;
}
}
#endregion
}
}
8 WebApi.Controllers.NoJsonDataBaseTestController.CreateMSDbBySqlClientAsync
/// <summary>
/// 【异步动态已经生数据库?--无需权限】
/// </summary>
/// <remarks>
/// 摘要:
/// 获取 1个值false(生成失败)/true(成功生成),该值指示是否通过动态“EntityFrameworkCore”中间件实例已经在指定数据库软件中成功生成了指定数据库及其表。
/// </remarks>
/// <returns>
/// 返回:
/// 1个值false(生成失败)/true(成功生成)。
/// </returns>
[HttpGet]
public async Task<MessageModel<bool>> CreateJsonEFCoreAsync()
{
//DataSettingsManager.SaveSettings(new DataConfig
//{
// DataProvider = DataProviderType.SqlServer,
// ConnectionString = "Data Source=.;Initial Catalog=ShopDemo;Integrated Security=False;Persist Security Info=False;User ID=zz;Password=zz;MultipleActiveResultSets=true;Trust Server Certificate=True"
//}, _fileProvider);
DataSettingsManager.SaveSettings(new DataConfig
{
DataProvider = DataProviderType.MySql,
ConnectionString = "Server=localhost;User ID=root;Password=zhoujian;Database=ShopDemo;Allow User Variables=True"
}, _fileProvider);
//动态实例化EntityFrameworkCore中间件。
EFCoreContext _context = EngineContext.Current.Resolve<EFCoreContext>();
MessageModel<bool> _messageModel = new MessageModel<bool>();
bool _isCreatedDatabase = await _context.CreateDatabaseAndTableAsync();
_messageModel.Response = _isCreatedDatabase;
if (_isCreatedDatabase)
{
_messageModel.Success = true;
_messageModel.Message = "已经成功在数据库软件中新建指定数据库及其表!";
}
else
{
_messageModel.Success = false;
_messageModel.Message = "数据库软件中新建指定数据库及其表失败!";
}
return _messageModel;
}
9 WebApi.Controllers.NoJsonDataBaseTestController.CreateMySqlDbBySqlClientAsync
/// <summary>
/// 【异步已经生成MySql数据库?--无需权限】
/// </summary>
/// <remarks>
/// 摘要:
/// 获取 1个值false(生成失败)/true(成功生成),该值指示是否通过“Microsoft.Data.SqlClient”中间件已经在“MySql”数据库软件中成功生成了指定数据库及其表。
/// 说明:
/// 1、数据库的生成是通过“Microsoft.Data.SqlClient”中间件。
/// 2、数据库中表生成是通过“EntityFrameworkCore”中间件。
/// 3、实际上数据库数据库及其表的生成可以不使用“Microsoft.Data.SqlClient”中间件直接通过“EntityFrameworkCore”中间件来完成。
/// 4、由于“EntityFrameworkCore”中间件封装太严密,使用“Microsoft.Data.SqlClient”中间件的最根本目的是可以使用最底层的方法来实现对数据的操作。
/// 5、在实际开发中第3方日志中间件(NLog/Log4net)与数据库的写入操作,也是通过“Microsoft.Data.SqlClient”中间件来实现的;读取操作则是通过“EntityFrameworkCore”中间件来完成。
/// 6、“Microsoft.Data.SqlClient”中间件可以以更加灵活的方式来实现当前程序对多数据库软件的支撑。
/// 注意:
/// 如果“appsettings.json”文件中没有“MySql”数据库软件的连接字符串,该方法需要执行两次。
/// </remarks>
/// <returns>
/// 返回:
/// 1个值false(生成失败)/true(成功生成)。
/// </returns>
[HttpGet]
public async Task<MessageModel<bool>> CreateMySqlDbBySqlClientAsync()
{
DataSettingsManager.SaveSettings(new DataConfig
{
DataProvider = DataProviderType.MySql,
ConnectionString = "Server=localhost;User ID=root;Password=zhoujian;Database=ShopDemo;Allow User Variables=True"
}, _fileProvider);
//获取数据库软件提供程序管理器类的1个指定实例。
var dataProvider = DataProviderManager.GetDataProvider(DataProviderType.MySql);
//通过“Microsoft.Data.SqlClient”中间件在“MySql”数据库软件中新建1个指定的数据库。
dataProvider.CreateDatabase(string.Empty);
//通过“EntityFrameworkCore”中间件为新建1个指定的数据库生成相应的表。
bool _isCreatedDatabase = false;
_isCreatedDatabase = await dataProvider.DatabaseExistsAsync();
//通过“EntityFrameworkCore”中间件为新建1个指定的数据库生成相应的表。
if (_isCreatedDatabase)
_isCreatedDatabase = await dataProvider.InitializeDatabaseAsync();
MessageModel<bool> _messageModel = new MessageModel<bool>();
_messageModel.Response = _isCreatedDatabase;
if (_isCreatedDatabase)
{
_messageModel.Success = true;
_messageModel.Message = "已经成功在“MySql”数据库软件中新建1个指定的数据库及其表!";
}
else
{
_messageModel.Success = false;
_messageModel.Message = "未在“MySql”数据库软件中新建1个指定的数据库及其表!!";
}
return _messageModel;
}
10 EntityFrameworkCore中间件通过迁移定义只自动生成表
10.1 引用Microsoft.EntityFrameworkCore.Tools
1、在Data项目中通过Nuget引用Microsoft.EntityFrameworkCore.Tools
2、在Data项目中通过Add-Migration Initialize命令自动生成迁移定义(Initialize:自动生成的迁移类名,这里特指:****.cs):
10.2 Data.EFCoreContext.CreateTableAsync
/// <summary>
/// 【异步自动生成表?】
/// <remarks>
/// 摘要:
/// 通过迁移定义在指定的数据库中生成相应的表。
/// </remarks>
/// </summary>
public async Task CreateTableAsync()
{
await Database.MigrateAsync();
}
10.3 引用Microsoft.EntityFrameworkCore.Design
在WebApi项目中通过Nuget引用Microsoft.EntityFrameworkCore.Design
通过调用CreateTableAsync EntityFrameworkCore中间件可以在Code-First模式下只自动生成表。
按F5执行程序不管在 “Microsoft SQL Server”数据库软件中,还是在“MySql”数据库软件中都能自动生“ShopDemo”数据库及其表。
对以上功能更为具体实现和注释见230125_018shopDemo(Microsoft.Data.SqlClient中间件数据库生成)。