在运行时间揭示数据提供商参数值
#database #csharp #dotnetcore

允许用户输入输入查询数据库表的动态值时,用户将输入一个不返回的值的可能性。

可以考虑的一个步骤是将SQL语句写入日志文件,但使用参数值将无法给定以下代码。

public static List<DataContainer> Example1(string countryName)
{
    List<DataContainer> list = new();

    using SqlConnection cn = new(ConnectionString());
    using SqlCommand cmd = new() { Connection = cn, CommandText = Statement1 };

    cmd.Parameters.Add("@CountryName", SqlDbType.NVarChar).Value = countryName;

    Console.WriteLine(cmd.CommandText);

我们得到以下内容。

screen shot

我们需要的是查看@CountryName的值,以便开发人员可以诊断问题是否与SQL相关或输入的值,该值不会返回记录。

无论用户在同一位置还是远程考虑以下路径。

安装以下Nuget软件包DbPeekQueryLibrary,它提供了一种简单的方法来查看参数值。

通过使用此软件包,开发人员可以做出确定,甚至不运行查询,例如,用户以领先空间输入Mexico

使用软件包/库我们可以看到问题。

screen shot

示例实现

第一步,我们并不总是想查看SQL,所以让我们在AppSettings.json文件中设置一个值以切换登录。

{
  "Debug": {
    "LogSqlCommand":  "True"
  }
}

添加一个Logger软件包,在这种情况下为SeriLog

对于示例项目,有几个软件包:

<ItemGroup>
   <PackageReference Include="Serilog" Version="2.12.0" />
   <PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
   <PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0" />
   <PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
</ItemGroup>

配置Serilog

public class SetupLogging
{
    public static void Production()
    {
        Log.Logger = new LoggerConfiguration()
            .WriteTo.File(Path.Combine(AppDomain
                    .CurrentDomain.BaseDirectory, "LogFiles", "Log.txt"),
                rollingInterval: RollingInterval.Day)
            .CreateLogger();
    }
}

创建一个从AppSettings.json读取设置的类

public class Configurations
{
    public static IConfigurationRoot GetConfigurationRoot()
    {
        return new ConfigurationBuilder()
            .SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
            .AddJsonFile("appsettings.json")
            .Build();
    }
}

创建一个单顿课程以阅读我们的记录SQL语句的设置。

internal sealed class ApplicationSettings
{
    private static readonly Lazy<ApplicationSettings> Lazy = 
        new(() => new ApplicationSettings());
    public static ApplicationSettings Instance => Lazy.Value;

    public bool LogSqlCommands { get; set; }
    private ApplicationSettings()
    {
        IConfigurationRoot configuration = 
            Configurations.GetConfigurationRoot();
        LogSqlCommands = Convert.ToBoolean(
            configuration.GetSection("Debug")["LogSqlCommand"]) ;
    }
}

安装以下Nuget软件包DbPeekQueryLibrary

接下来将断言写入一个方法,该方法从数据库请求数据,该代码是从本文的源代码中获取的,例如

if (ApplicationSettings.Instance.LogSqlCommands)
{
    Log.Information($"{nameof(SqlServerOperations)}.{nameof(Example1)}\n{cmd.ActualCommandText()}");
}

使用"LogSqlCommand": "True" sql语句记录。

在以下屏幕截图中,我阅读了日志和增强零件以进行澄清。

screen shot

使用不同的数据库。

默认数据库是sql-server,默认值期望第一个参数的@,因此无需完成。要与Oracle一起使用,将第一个参数设置为Oracle

这些是各种提供商

public enum CommandProvider
{
    SqlServer,
    Access,
    SqLite,
    Oracle
}

这真的与Microsoft Access合作吗?不是在使用?字符时,对于那些与访问工作大量合作的人知道,我们可以设置名为参数,只需确保它们是可行的位置即可。

源代码

克隆以下GitHub repository

.NET框架类版本

NuGet package覆盖框架4.6至4.8