(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

C# & Oracle - заметки на полях - 2

уть было не забыл про CLOB.



Я не буду ходить вокруг, кому интересно могут ознакомиться с предыдущем топиком



Здесь я хочу привести свой код, для работы с БД Oracle (Не вставил в предыдущий топик т.к. полилось много текста и НЛО послало процесс сохранения лесом).

Вообще CLOB(LOB\BLOB) довольно интересен. Работа с ним отличается от работы с другими объектами. Детальное описание вы так же можете посмотреть в MSDN.
Скажу лишь то что сделать что-то вроде:

OracleParameter someClob = new OracleParameter()
{
  ParameterName = "some_clob",
  Direction = ParameterDirection.Input,
  OracleType = OracleType.Clob,
  Value = clobData
};


не выйдет, подход должен быть тоньше.

На сладкое

У программистов и дизайнеров, да и наверное у всех людей, есть общая черта, я называю её "кнопка MakeItPizdato". Т.е. получить при наименьших затратах, чего угодно, максимальную эффектиность\продуктивность\подставить по своему желанию.
Поэтому я написал свой код (критике буду только рад! но разумной критике ;) ), которым решил поделиться:

Работа с БД разбита на несколько частей:
Фабрика - отвечает за полную работу с БД

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OracleClient;
using System.Linq;
using Core.Extensions;

namespace TestApp.Core
{
  class OracleFactory : IDisposable
  {
    #region Variables
    private bool _disposed = false;

    private String _connectionString = "Data Source=***;Password=***;User ID=***";
    private OracleConnection _connection;
    private String _lastCommandName;
    #endregion

    #region Constructor

    public OracleFactory()
    {
      InitializeConnection();
    }

    public OracleFactory(String connectionString)
    {
      _connectionString = connectionString;
      InitializeConnection();
    }

    private void InitializeConnection()
    {
      Commands = new Dictionary<String, OracleCommand>();
      RollbackCommandNames = new List<string>();

      try
      {
        _connection = new OracleConnection(_connectionString);
        _connection.Open();
      }
      catch (OracleException oraEx)
      {
        Console.WriteLine("Connection failed with message: " + oraEx.ToString());
      }
    }

    #endregion

    #region IDisposable
    ~OracleFactory()
    {
      Dispose(false);
    }

    public void Dispose()
    {
      Dispose(true);
      GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposeManagedResources)
    {
      if (!_disposed)
      {
        foreach (String commandName in Commands.Keys)
        {
          if (RollbackCommandNames.Contains(commandName))
            Commands[commandName].Transaction.Rollback();
          else
            Commands[commandName].Transaction.Commit();
        }

        if (disposeManagedResources)
        {
          foreach (String commandName in Commands.Keys)
          {
            Commands[commandName].Dispose();
          }
          //Dispose connection information
          _connection.Close();
          _connection.Dispose();
        }

        _disposed = true;
      }
    }
    #endregion

    public OracleConnection Connection
    {
      get
      {
        return (_connection);
      }
    }

    public Dictionary<String, OracleCommand> Commands
    {
      get;
      private set;
    }

    public List<String> RollbackCommandNames
    {
      get;
      private set;
    }

    /// <summary>
    /// Last used command name
    /// </summary>
    /// <exception cref="System.ArgumentException"/>
    public String LastCommandName
    {
      get
      {
        if (_lastCommandName == String.Empty)
          throw new ArgumentException("LastCommandName is not specified");

        return (_lastCommandName);
      }
      set
      {
        _lastCommandName = value;
      }
    }

    /// <summary>
    /// Last used command
    /// </summary>
    public OracleCommand LastCommand
    {
      get
      {
        return (Commands[LastCommandName]);
      }
    }

    public Object this[String commandName, String parameterName]
    {
      get
      {
        if (!Commands.Keys.Contains(commandName))
          throw new OracleFactoryException();

        return (Commands[commandName].Parameters[parameterName].Value);
      }
      set
      {
        Commands[commandName].Parameters[parameterName].Value = value;
      }
    }

    public Object this[String parameterName]
    {
      get
      {
        return (this[LastCommandName, parameterName]);
      }
      set
      {
        this[LastCommandName, parameterName] = value;
      }
    }

    /// <summary>
    /// Allow get oracle parameter value
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="parameterName">Oracle parameter name</param>
    /// <returns>Oracle parameter value</returns>
    /// <exception cref="System.InvalidCastException"/>
    /// <exception cref="System.ArgumentNullException" />
    public T GetParameterValue<T>(String parameterName)
    {
      return ((T)Convert.ChangeType(this[parameterName], typeof(T)));
    }

    /// <summary>
    /// Creates a new Oracle`s command (default for stored procedures)
    /// </summary>
    /// <exception cref="Core.DL.OracleManagerException">
    /// </exception>
    /// <param name="commandName">Oracle`s command name</param>
    public void CreateCommand(String commandName)
    {
      CreateCommand(commandName, CommandType.StoredProcedure);
    }

    /// <summary>
    /// Creates a custom Oracle`s command
    /// </summary>
    /// <exception cref="Core.DL.OracleManagerException">
    /// </exception>
    /// <param name="commandName">Oracle command name</param>
    /// <param name="commandType">Oracle command type</param>
    public void CreateCommand(String commandName, CommandType commandType)
    {
      if (Commands.Keys.Contains(commandName))
        throw new OracleFactoryException();

      LastCommandName = commandName;

      Commands[commandName] = new OracleCommand(commandName, _connection);
      Commands[commandName].CommandType = commandType;
      Commands[commandName].Transaction = Connection.BeginTransaction();
    }

    public void ClearParameters()
    {
      LastCommand.Parameters.Clear();
    }

    public void AddParameter(String parameterName, OracleType parameterType, Object parameterValue)
    {
      AddParameter(LastCommandName, parameterName, parameterType, parameterValue, ParameterDirection.Input);
    }

    public void AddParameter(String parameterName, OracleType parameterType, Object parameterValue, ParameterDirection parameterDirection)
    {
      AddParameter(LastCommandName, parameterName, parameterType, parameterValue, parameterDirection);
    }

    public void AddParameter(String commandName, String parameterName, OracleType parameterType,
      Object parameterValue, ParameterDirection parameterDirection)
    {
      if (!Commands.Keys.Contains(commandName))
        throw new OracleFactoryException();

      if (parameterType == OracleType.Clob)
        parameterValue = OracleFactory.PrepareCLOB(Commands[commandName], parameterValue.ToString());

      Commands[commandName].Parameters.Add(new OracleParameter(parameterName, parameterType)
      {
        Direction = parameterDirection,
        Value = parameterValue ?? DBNull.Value
      });
    }

    public void ExecuteNonQuery()
    {
      ExecuteNonQuery(LastCommandName);
    }

    public void ExecuteNonQuery(String commandName)
    {
      if (!this.Commands.ContainsKey(commandName))
        throw new OracleFactoryException();

      Commands[commandName].ExecuteNonQuery();
    }

    public OracleDataReader ExecuteReader()
    {
      return (ExecuteReader(LastCommandName));
    }

    public OracleDataReader ExecuteReader(String commandName)
    {
      OracleDataReader dataReader = Commands[commandName].ExecuteReader();

      return (dataReader);
    }

    public void Rollback(String commandName)
    {
      if (!RollbackCommandNames.Contains(commandName))
      {
        RollbackCommandNames.Add(commandName);
      }
    }

    public void Rollback()
    {
      Rollback(LastCommandName);
    }

    #region Static members

    public static OracleLob PrepareCLOB(OracleCommand command, String data)
    {
      OracleLob clob = CreateLob(command, OracleType.Clob);
      byte[] byteData = System.Text.Encoding.Unicode.GetBytes(data);

      clob.BeginBatch(OracleLobOpenMode.ReadWrite);
      clob.Write(byteData, 0, byteData.Length);
      clob.EndBatch();

      return (clob);
    }

    public static OracleLob CreateLob(OracleCommand command, OracleType lobType)
    {
      if (command.Transaction == null)
        throw new OracleFactoryException("Parameter command should contains transaction value");

      if (lobType != OracleType.Clob && lobType != OracleType.Blob)
        throw new OracleFactoryException("Thhis method is used only for creation LOB objects");

      ////Save previous information about a command
      String previousCommand = command.CommandText;
      CommandType previousCommandType = command.CommandType;
      OracleParameterCollection previousParameters = new OracleParameterCollection();
      command.Parameters.MakeClone(previousParameters);

      //Prepare for creating LOB object
      command.Parameters.Clear();

      command.CommandType = CommandType.Text;
      command.CommandText = String.Format("declare xx {0}; begin dbms_lob.createtemporary(xx, false, 0); :tempLob := xx; end;",
        lobType == OracleType.Clob ? "clob" : "blob");
      command.Parameters.Add(new OracleParameter("tempLob", lobType) { Direction = ParameterDirection.Output });
      command.ExecuteNonQuery();

      OracleLob retLob = command.Parameters["tempLob"].Value as OracleLob;

      command.Parameters.Clear();

      command.CommandText = previousCommand;
      command.CommandType = previousCommandType;
      previousParameters.MakeClone(command.Parameters);

      return (retLob);
    }

    #endregion
  }
}


Я подсел на использование расширяющих методов (Extensions). А в рамках того что мне нужно было подготовить коллекцию параметров для использования с типами LOB (сохранить, а затем восстановить), я придумал такое расширение:

using System.Data.OracleClient;

namespace Core.Extensions
{
  public static class OracleParameterCollectionExtensions
  {
    public static void MakeClone(this OracleParameterCollection sourceCollection, OracleParameterCollection outCollection)
    {
      foreach (OracleParameter parameter in sourceCollection)
      {
        OracleParameter newParam = new OracleParameter()
        {
          Direction = parameter.Direction,
          IsNullable = parameter.IsNullable,
          OracleType = parameter.OracleType,
          ParameterName = parameter.ParameterName,
          Value = parameter.Value
        };

        outCollection.Add(newParam);
      }
    }
  }
}


* This source code was highlighted with Source Code Highlighter.


Начав использовать данный код сегодня, вы бесплатно получаете + Exception!:

using System;

namespace TestApp.Core
{
  public class OracleFactoryException : Exception
  {
    public OracleFactoryException()
    {
    }

    public OracleFactoryException(String exMessage)
      : base(exMessage)
    {

    }
  }

}


Для меня телодвижений стало меньше, теперь добавление выглядит так:

public void AddConscript(string firstName, string lastName, int ages, float growth, string biograpby)
{
  using (OracleFactory factory = new OracleFactory())
  {
    factory.CreateCommand("ADD_CONscript");

    factory.AddParameter("FirstNameIn", OracleType.VarChar, firstName);
    factory.AddParameter("LastNameIn", OracleType.VarChar, lastName);
    factory.AddParameter("AgesIn", OracleType.Number, ages);
    factory.AddParameter("GrowthIn", OracleType.Float, growth);
    factory.AddParameter("BiographyIn", OracleType.Clob, biograpby);
  }
}


Код упрощён, можно использовать тот же CLOB прозрачно относительно других типов.
Если вам необходимо получить значение определённого параметра следующим образом:

factory.GetParameterValue<String>("BiographyIn");


Те кто поковыряются в коде, найдут ещё много чего интересного ;).

Вы спросите почему именно CLOB? Я отвечу - мне другие LOB пока были не нужны, а код я точил под себя ;).

Ссылки по теме


 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 09.11.2009 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
Oracle Database Personal Edition Named User Plus Software Update License & Support
Oracle Database Standard Edition 2 Named User Plus License
Oracle Database Personal Edition Named User Plus License
Oracle Database Standard Edition 2 Processor License
Quest Software. Toad for Oracle Development Suite
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Новости ITShop.ru - ПО, книги, документация, курсы обучения
Программирование на Microsoft Access
CASE-технологии
СУБД Oracle "с нуля"
Вопросы и ответы по MS SQL Server
Delphi - проблемы и решения
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100