C# 使用Dapper将C bool作为参数传递给Oracle

C# 使用Dapper将C bool作为参数传递给Oracle,c#,oracle,dapper,C#,Oracle,Dapper,我试图使用Dapper将bool作为参数传递给Oracle,将其转换为数据库上的1/0字段,如下所示: public class Customer { public bool Active { get; set; } } static void InsertCustomer() { var customer = connect.QueryFirst<Customer>("select 1 active from dual"); // this works co

我试图使用Dapper将bool作为参数传递给Oracle,将其转换为数据库上的1/0字段,如下所示:

public class Customer
{
    public bool Active { get; set; }
}
static void InsertCustomer()
{
    var customer = connect.QueryFirst<Customer>("select 1 active from dual"); // this works
    connect.Execute("insert into customers(active) values(:active)", customer); // this doesn't
}
但这引发了一个例外:

System.ArgumentException:'值不在预期范围内 射程。”

我知道我可以创建另一个属性public int ActiveInt=>Active?1 : 2; 但是我希望保持我的POCO类尽可能干净,特别是因为属性需要是公共的,以便Dapper使用它们作为参数

我尝试创建布尔类型处理程序,但它仅适用于查询列,不适用于参数:

我还需要将整个对象作为参数传递,因此在传递参数时无法进行转换


有什么方法可以做到这一点吗?

我没有Oracle DB可供使用,但是,根据我在网上看到的内容以及我对dapper的了解,您可以尝试将您的对象转换为dapper dynamic parameters对象,并在每个参数名称的前面插入Oracle所需的:。您可以使用我组合的这个扩展方法:

public static class ParameterExtensions
  {
    /// <summary>
    /// Extension method that converts any single dimensional object into Dapper's Dynamic Parameters
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="incoming"></param>
    /// <param name="allowNulls">Provide true to allow nulls to be mapped</param>
    /// <returns></returns>
    public static DynamicParameters ConvertToDynamicParameters<T>(this T incoming, bool allowNulls = false)
    {
      DynamicParameters dynamicParameters = new DynamicParameters();
      foreach (PropertyInfo property in incoming.GetType().GetProperties())
      {
        object value = GetPropValue(incoming, property.Name);
        if (value != null || allowNulls) dynamicParameters.Add($":{property.Name}", value);
      }
      return dynamicParameters;
    }

    private static object GetPropValue(object src, string propName)
    {
      return src.GetType().GetProperty(propName)?.GetValue(src, null);
    }
  }
这是您的实施将更改为:

public class Customer
{
  public bool Active { get; set; }
}
static void InsertCustomer()
{
  var customer = connect.QueryFirst<Customer>("select 1 active from dual"); // this works
  connect.Execute(@"insert into customers(active) values(:active)", customer.ConvertToDynamicParameters()); // this doesn't
}
请让我知道这是否对你有效


**注意:您需要在查询和对象上使参数大小写匹配。例如,在您的客户对象上有Customer.Active。此名称必须匹配:Active。

我使用Dapper.SqlMapper.AddTypeMapType,DbType方法

public class Customer
{
    public bool Active { get; set; }
}

class Program : IDisposable
{
    private readonly DbConnection _connection;

    public Program()
    {
        _connection = DbOpen();
    }

    static void Main(string[] args)
    {
        SqlMapper.AddTypeMap(typeof(bool), DbType.Int32);

        using (var program = new Program())
        {
            program.Run();
        }
    }

    private void Run()
    {
        _connection.Execute($"INSERT INTO customers ( active ) VALUES (:Activate)", new { Activate = true });
        _connection.Execute($"INSERT INTO customers ( active ) VALUES (:Activate)", new { Activate = false });

        var customers = new List<Customer>()
        {
            new Customer() {Active = true},
            new Customer() {Active = false}
        };
        _connection.Execute($"INSERT INTO customers ( active ) VALUES (:{nameof(Customer.Active)})", customers);

        var results = _connection.Query<Customer>("SELECT * FROM customers");
        foreach (var customer results)
        {
            Console.WriteLine($"{nameof(Customer.Active)} is {customer.Active}");
        }
    }

    private static DbConnection DbOpen()
    {
        var connectionSetting = ConfigurationManager.ConnectionStrings["oracle"];
        var dbFactory = DbProviderFactories.GetFactory(connectionSetting.ProviderName);
        var conn = dbFactory.CreateConnection();
        conn.ConnectionString = connectionSetting.ConnectionString;
        conn.Open();
        return conn;
    }

    public void Dispose()
    {
        _connection?.Dispose();
    }
}

如果我们谈论.NET核心使用Dapper连接到Oracle DB。 我使用这个程序,它是有效的。 Nuget安装Dapper.Oracle

例如:

在您的C模型中:

public bool someBoolValue { get; set; }
在您的C存储库中:

using Dapper;
using Dapper.Oracle;

//in your method
var parameters = new OracleDynamicParameters();
parameters.Add("SOMESQLVARIABLE", yourModel.someBoolValue, OracleMappingType.Int32, ParameterDirection.Input);
parameters.Add("OUT_REFCURSOR", dbType: OracleMappingType.RefCursor, direction: ParameterDirection.Output);
var result = await _dbConnection.ExecuteAsync("my_proc",
                                              parameters,
                                              commandType: CommandType.StoredProcedure);
return result;
DB程序:

PROCEDURE my_proc(
    SOMESQLVARIABLE IN    NUMBER,
    out_refcursor   OUT   SYS_REFCURSOR
)AS
BEGIN
    OPEN out_refcursor FOR SELECT
                               some_column
                           FROM
                               my_table
                           WHERE 
                               my_col = SOMESQLVARIABLE; -- my_col is NUMBER(1,0)

END my_proc;