使用Dapper与Oracle用户定义类型

5

有没有一种方法可以使用Dapper与由存储过程返回的Oracle用户定义类型一起使用? Dapper似乎可以与存储过程配合使用(请参见使用返回游标的Oracle存储过程和Dapper)。

var p = new OracleDynamicParameters();
p.Add("param_list", null, OracleDbType.Object, ParameterDirection.Output);
p.Add("param_reco", null, OracleDbType.Object, ParameterDirection.Output);

在我的例子中,我添加了一个UDT集合对象作为输出参数(param_list)。我使用自定义的OracleDynamicParameters,发布在Dapper - Oracle和Microsoft .NET的Micro ORM上。
越多地阅读ORM相关的内容,越能够看到Oracle UDT对象是一个障碍。在这种情况下,纯ADO.NET和生成的C#实体类似乎是唯一的方法。也许automapper.org对于将领域对象映射到UDT对象可能有用。

目前发生了什么?是否出现错误?还是没有更新输出参数?或者...? - Marc Gravell
每次调用Query都会产生一个ArgumentException(ODAC set_value)。但这可能是由于使用了经典的ODAC程序集。我已经用经典的ODP.NET的Oracle.DataAccess.Client替换了Oracle.ManagedDataAccess.Client。托管的ODP驱动程序仍处于测试版。 - Marco Mayer
1个回答

2

建议使用OracleCustomTypeMapping属性和OracleObjectMapping属性。我不记得我从哪里得到这个想法了,但是...

public interface INullableOracleCustomType: INullable,  IOracleCustomType
    {
    }

[OracleCustomTypeMapping("<YOUR_SCHEMA_NAME>.<UDT_OBJECT_NAME>")]
    public class ParameterObject : INullableOracleCustomType
    {
        private bool objectIsNull;

        #region constructor

        public ParameterObject()
        { }

        public ParameterObject(string parameterName, string parameterValue)
        {
            this.ParameterName = parameterName;
            this.ParameterValue = parameterValue;
        }

        #endregion

        #region properties
        [OracleObjectMappingAttribute("PARAMETERNAME")]
        public string ParameterName { get; set; }

        [OracleObjectMappingAttribute("PARAMETERVALUE")]
        public string ParameterValue { get; set; }

        public static ParameterObject Null
        {
            get
            {
                ParameterObject parameterObject = new ParameterObject();
                parameterObject.objectIsNull = true;
                return parameterObject;
            }
        }

        #endregion

        #region INullable Members

        public bool IsNull
        {
            get { return objectIsNull; }
        }

        #endregion

        #region IOracleCustomType
        public void FromCustomObject(Oracle.DataAccess.Client.OracleConnection con, IntPtr pUdt)
        {
            // Convert from the Custom Type to Oracle Object
            if (!string.IsNullOrEmpty(ParameterName))
            {
                OracleUdt.SetValue(con, pUdt, "PARAMETERNAME", ParameterName);
            }
            if (!string.IsNullOrEmpty(ParameterValue))
            {
                OracleUdt.SetValue(con, pUdt, "PARAMETERVALUE", ParameterValue);
            }
        }

        public void ToCustomObject(Oracle.DataAccess.Client.OracleConnection con, IntPtr pUdt)
        {
            ParameterName = (string)OracleUdt.GetValue(con, pUdt, "PARAMETERNAME");
            ParameterValue = (string)OracleUdt.GetValue(con, pUdt, "PARAMETERVALUE");
        }

        #endregion
    }

示例用法...

public static OracleParameter CreateCustomTypeArrayInputParameter<T>(string name, string oracleUDTName, T value)
            where T : INullableOracleCustomType
        {
            OracleParameter parameter = new OracleParameter();
            parameter.ParameterName = name;
            parameter.OracleDbType = OracleDbType.Array;
            parameter.Direction = ParameterDirection.Input;
            parameter.UdtTypeName = oracleUDTName;
            parameter.Value = value;
            return parameter;
        }

Oracle似乎对模式/类型/对象名称必须使用大写字母感到挑剔。


我知道这是一个非常古老的帖子,但我希望这个问题能得到回答: 假设我们不想要一个数组,而只是一个自定义的UDT返回参数(例如),那么“chat”会是OracleDbType吗? - Cromm
有关 OracleDbType 枚举的文档,请参见:https://docs.oracle.com/cd/E85694_01/ODPNT/OracleDbTypeEnumerationType.htm#ODPNT2286 - kpollock

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接