sql >> Databasteknik >  >> RDS >> Oracle

C#:Skicka en användardefinierad typ till en lagrad Oracle-procedur

Här är en hjälpare som jag använde för att arbeta med lagrade procedurer i Oracle:

internal class OracleDataHelper
{
    #region Variables
    private static readonly string _connectionString;
    #endregion

    #region Constructors
    static OracleDataHelper()
    {
        //_connectionString = ConfigurationManager.ConnectionStrings["..."]
        //    .ConnectionString;
    }
    #endregion

    public static object ExecuteScalar(string query)
    {
        object result;
        using (OracleConnection conn = new OracleConnection(ConnectionString))
        {
            conn.Open();
            OracleCommand command = new OracleCommand(query, conn);
            command.CommandType = CommandType.Text;

            result = command.ExecuteScalar();

            command.Dispose();
            conn.Close();
        }

        return result;
    }

    public static object ExecuteScalar(
        string query, 
        params object[] parameters)
    {
        object result;
        using (OracleConnection conn = new OracleConnection(ConnectionString))
        {
            conn.Open();
            OracleCommand command = new OracleCommand(query, conn);
            command.CommandType = CommandType.Text;
            command.Parameters.AddRange(
                ConvertParameters(parameters)
            );

            result = command.ExecuteScalar();

            command.Dispose();
            conn.Close();
        }

        return result;
    }

    public static int ExecuteNonQuery(string query)
    {
        return ExecuteNonQuery(query, new List<OracleParameter>());
    }

    public static int ExecuteNonQuery(
        string query, 
        List<OracleParameter> parameters)
    {
        int result = 0;

        using (OracleConnection conn = new OracleConnection(ConnectionString))
        {
            conn.Open();
            OracleCommand command = new OracleCommand(query, conn);
            command.CommandType = CommandType.Text;
            command.BindByName = true;
            command.Parameters.AddRange(
                ConvertParameters(parameters.ToArray())
            );

            result = command.ExecuteNonQuery();

            command.Dispose();
            conn.Close();
        }

        return result;
    }

    public static int ExecuteNonQuery(
        string query,
        params object[] parameters)
    {
        int result = 0;
        using (OracleConnection conn = new OracleConnection(ConnectionString))
        {
            conn.Open();
            OracleCommand command = new OracleCommand(query, conn);
            command.BindByName = true;
            command.CommandType = CommandType.Text;
            command.Parameters.AddRange(ConvertParameters(parameters));

            result = command.ExecuteNonQuery();

            command.Dispose();
            conn.Close();
        }

        return result;
    }

    public static OracleDataReader ExecuteReader(
        OracleConnection conn,
        string commandText
        )
    {
        OracleCommand command = new OracleCommand(commandText, conn);

        return command.ExecuteReader();
    }

    public static IDataReader ExecuteReader(
        OracleConnection conn, 
        string spName, 
        out List<OracleParameter> outParameters, 
        params object[] parameters)
    {
        throw new NotImplementedException();
    }

    public static int ExecuteProcedure(
        string spName,
        out OutputParameters outputParameters,
        params object[] parameters)
    {
        int result = 0;

        using (OracleConnection conn = new OracleConnection(ConnectionString))
        {
            conn.Open();
            OracleCommand command = new OracleCommand(spName, conn);
            command.CommandType = CommandType.StoredProcedure;
            command.Parameters.AddRange(ConvertParameters(parameters));

            result = command.ExecuteNonQuery();
            outputParameters = GetOutputParameters(command.Parameters);

            command.Dispose();
            conn.Close();
        }

        return result;
    }

    public static int ExecuteProcedure(
        string spName,
        params object[] parameters)
    {
        int result = 0;

        using (OracleConnection conn = new OracleConnection(ConnectionString))
        {
            conn.Open();
            OracleCommand command = new OracleCommand(spName, conn);
            command.CommandType = CommandType.StoredProcedure;
            command.Parameters.AddRange(ConvertParameters(parameters));

            result = command.ExecuteNonQuery();

            command.Dispose();
            conn.Close();
        }

        return result;
    }

    public static OracleDataReader ExecuteProcedure(
        OracleConnection conn,
        string spName,
        out OutputParameters outputParameters,
        params object[] parameters
        )
    {
        OracleCommand command = new OracleCommand(spName, conn);
        command.CommandType = CommandType.StoredProcedure;
        command.Parameters.AddRange(ConvertParameters(parameters));

        OracleDataReader reader = command.ExecuteReader();
        outputParameters = GetOutputParameters(command.Parameters);
        command.Dispose();

        return reader;
    }

    public static OracleDataReader ExecuteProcedure(
        OracleConnection conn,
        string spName,
        params object[] parameters
        )
    {
        OracleCommand command = new OracleCommand(spName, conn);
        command.CommandType = CommandType.StoredProcedure;
        command.Parameters.AddRange(ConvertParameters(parameters));

        OracleDataReader reader = command.ExecuteReader();
        command.Dispose();

        return reader;
    }

    private static OracleParameter[] ConvertParameters(object[] parameters)
    {
        parameters = parameters ?? new object[] { };

        int parametersCount = parameters.Length;
        OracleParameter[] parametersArray = 
            new OracleParameter[parametersCount];

        for (int i = 0; i < parametersCount; i++)
        {
            object parameter = parameters[i];
            OracleParameter oracleParameter;

            if (parameter is OracleParameter)
            {
                oracleParameter = (OracleParameter)parameter;
                if (null == oracleParameter.Value)
                {
                    oracleParameter.Value = DBNull.Value;
                }
            }
            else
            {
                oracleParameter = new OracleParameter();

                oracleParameter.Value = parameter == null ?
                    DBNull.Value :
                    parameter;
            }

            // adding udt mapping for the parameter
            if (oracleParameter.Value != null && 
                oracleParameter.Value is IOracleCustomTypeFactory)
            {
                MemberInfo info = oracleParameter.Value.GetType();
                OracleCustomTypeMappingAttribute[] attributes =  
                        info.GetCustomAttributes(
                    typeof(OracleCustomTypeMappingAttribute), 
                        false
                    ) as OracleCustomTypeMappingAttribute[];
                if (null != attributes && attributes.Length > 0)
                {
                    oracleParameter.UdtTypeName = attributes[0].UdtTypeName;
                }
            }

            parametersArray[i] = oracleParameter;
        }

        return parametersArray;
    }

    private static OutputParameters GetOutputParameters(
        OracleParameterCollection parameters)
    {
        OutputParameters outputParameters = new OutputParameters();
        foreach (OracleParameter parameter in parameters)
        {
            if (parameter.Direction == ParameterDirection.Output)
                outputParameters.Add(parameter);
        }

        return outputParameters;
    }

    internal static string ConnectionString
    {
        get { return _connectionString; }
    }
}

Dessa metoder fungerar med UDT likaväl som de fungerar med enkla parametrar.

Här är ett exempel på UDT-entitet:

[Serializable]
[OracleCustomTypeMappingAttribute("MDSYS.SDO_GEOMETRY")]
public class SdoGeometry : IOracleCustomTypeFactory, 
                           IOracleCustomType, 
                           ICloneable, INullable
{
    #region Variables
    private int _sdoGType;
    private int _sdoSrid;
    private SdoPoint _sdoPoint;
    private SdoElemInfo _sdoElemInfo;
    private SdoOrdinates _sdoOrdinate;

    private bool _sdoGTypeIsNull;
    private bool _sdoSridIsNull;
    #endregion

    #region Properties
    [OracleObjectMappingAttribute("SDO_GTYPE")]
    public int SdoGType
    {
        get { return _sdoGType; }
        set
        {
            _sdoGType = value;
            _sdoGTypeIsNull = false;
        }
    }

    public SdoGeometryType SdoGeometryType
    {
        get { return (Entities.Geometry.SdoGeometryType)(SdoGType % 100); }
    }

    public int Dimensions
    {
        get { return (int)(SdoGType / 1000); }
    }

    public int LrsDimensions
    {
        get { return (int)((SdoGType / 100) % 10); }
    }

    [OracleObjectMappingAttribute("SDO_SRID")]
    public int SdoSrid
    {
        get { return _sdoSrid; }
        set
        {
            _sdoSrid = value;
            _sdoSridIsNull = false;
        }
    }

    [OracleObjectMappingAttribute("SDO_POINT")]
    public SdoPoint SdoPoint
    {
        get { return _sdoPoint; }
        set { _sdoPoint = value; }
    }

    [OracleObjectMappingAttribute("SDO_ELEM_INFO")]
    public SdoElemInfo SdoElemInfo
    {
        get { return _sdoElemInfo; }
        set { _sdoElemInfo = value; }
    }

    [OracleObjectMappingAttribute("SDO_ORDINATES")]
    public SdoOrdinates SdoOrdinates
    {
        get { return _sdoOrdinate; }
        set { _sdoOrdinate = value; }
    }

    public static SdoGeometry Null
    {
        get
        {
            SdoGeometry obj = new SdoGeometry();

            return obj;
        }
    }
    #endregion

    #region Constructors
    public SdoGeometry()
    {
        _sdoGTypeIsNull = true;
        _sdoSridIsNull = true;
        _sdoElemInfo = SdoElemInfo.Null;
        _sdoOrdinate = SdoOrdinates.Null;
        _sdoPoint = SdoPoint.Null;
    }

    public SdoGeometry(SdoGeometry obj)
    {
        if (obj != null && this != obj)
        {
            SdoGType = obj.SdoGType;
            SdoSrid = obj.SdoSrid;
            SdoPoint = (SdoPoint)obj.SdoPoint.Clone();
            SdoElemInfo = (SdoElemInfo)obj.SdoElemInfo.Clone();
            SdoOrdinates = (SdoOrdinates)obj.SdoOrdinates.Clone();
        }
    }

    public SdoGeometry(
        int gType,
        int srid,
        SdoPoint point,
        SdoElemInfo elemInfo,
        SdoOrdinates ordinate)
    {
        SdoGType = gType;
        SdoSrid = srid;
        SdoPoint = (SdoPoint)point.Clone();
        SdoElemInfo = (SdoElemInfo)elemInfo.Clone();
        SdoOrdinates = (SdoOrdinates)ordinate.Clone();
    }
    #endregion

    #region ICloneable Members
    public object Clone()
    {
        return new SdoGeometry(this);
    }
    #endregion

    #region IOracleCustomType Members
    public void FromCustomObject(OracleConnection con, IntPtr pUdt)
    {
        if (!_sdoGTypeIsNull)
            OracleUdt.SetValue(con, pUdt, "SDO_GTYPE", SdoGType);
        if (!SdoOrdinates.IsNull)
            OracleUdt.SetValue(con, pUdt, "SDO_ORDINATES", SdoOrdinates);
        if (!SdoElemInfo.IsNull)
            OracleUdt.SetValue(con, pUdt, "SDO_ELEM_INFO", SdoElemInfo);
        if (!_sdoSridIsNull)
            OracleUdt.SetValue(con, pUdt, "SDO_SRID", SdoSrid);
        else
            OracleUdt.SetValue(con, pUdt, "SDO_SRID", DBNull.Value);
        if (!SdoPoint.IsNull)
            OracleUdt.SetValue(con, pUdt, "SDO_POINT", SdoPoint);
    }

    public void ToCustomObject(OracleConnection con, IntPtr pUdt)
    {
        object sdoGType = OracleUdt.GetValue(con, pUdt, "SDO_GTYPE");
        _sdoGTypeIsNull = sdoGType == null || sdoGType is DBNull;
        if (!_sdoGTypeIsNull)
            SdoGType = (int)sdoGType;
        SdoOrdinates = 
            (SdoOrdinates)OracleUdt.GetValue(con, pUdt, "SDO_ORDINATES");
        SdoElemInfo = 
            (SdoElemInfo)OracleUdt.GetValue(con, pUdt, "SDO_ELEM_INFO");
        object sdoSrid = OracleUdt.GetValue(con, pUdt, "SDO_SRID");
        if (!(sdoSrid == null || sdoSrid is DBNull))
            SdoSrid = (int)sdoSrid;
        SdoPoint = (SdoPoint)OracleUdt.GetValue(con, pUdt, "SDO_POINT");
    }
    #endregion

    #region INullable Members
    public bool IsNull
    {
        get { return _sdoGTypeIsNull; }
    }
    #endregion

    #region IOracleCustomTypeFactory Members
    public IOracleCustomType CreateObject()
    {
        return new SdoGeometry();
    }
    #endregion
}

P.S. Under mitt projekt släppte Oracle 3 versioner av ODP.NET. Det intressanta:koden som fungerade för version 2.111.6.10 av Oracle.DataAcess.dll fungerade inte alls för 2.111.6.20!

Vet inte vilken version av ODP.NET som är aktuell nu men exemplen jag postade ovan fungerar bra med 2.111.6.10.

Hoppas det här hjälper. Lycka till!



  1. Är MS-SQL OCH/ELLER villkorligt (utför kortslutningsutvärdering)?

  2. Begränsa en länkad server till en enda lokal inloggning (T-SQL-exempel)

  3. PostgreSQL-funktion / lagrad procedur CURRENT_TIMESTAMP ändras inte

  4. SQLite GLOB