уть было не забыл про 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 пока были не нужны, а код я точил под себя ;).
Ссылки по теме