DbCommand и параметризованный SQL, ORACLE против SQL Server - PullRequest
10 голосов
/ 14 марта 2011

У меня есть приложение, которое, помимо прочего, будет хранить различные данные в базе данных. База данных может быть ORACLE или SQL Server. SQL создается динамически на основе конфигурации и значений, выбранных во время выполнения.

Используя DbProviderFactory, мои методы db могут работать с ORACLE или SQL Server без написания специального кода для какой-либо из баз данных, за исключением одной вещи; параметры / переменные связывания. Для ORACLE мне нужно использовать ":ParameterName", тогда как для SQL Server мне нужно использовать "@ParameterName". Есть ли способ сделать это универсальным?

Пример кода:

public class DbOperations
{
    private DbProviderFactory m_factory;
    private DbConnection m_CN;

    ...

    private void InsertToDb(ValueType[] values, ColumnType[] columns)
    {     
        DbCommand Cmd = m_factory.CreateCommand();
        Cmd.Connection = m_CN;

        StringBuilder sql = new StringBuilder();
        sql.Append("INSERT INTO ");
        sql.Append(DestinationTable);
        sql.Append(" (");

        for (int i = 0; i < columns.Length; i++)
        {
            sql.Append(columns[i].ColumnName);
            if (i < columns.Length - 1) 
            sql.Append(", ");
        }
        sql.Append(") VALUES (");

        for (int i = 0; i < values.Length; i++)
        {        
            //sql.Append(String.Format(":{0}", columns[i].ColumnName));  //ORACLE
            sql.Append(String.Format("@{0}", columns[i].ColumnName)); // SQL Server
        }       

        DbParameter param = m_factory.CreateParameter();
        param.Direction = ParameterDirection.Input;
        param.ParameterName = columns[i].ColumnName;
        param.Value = values[i];
        Cmd.Parameters.Add(param);

        if (i < columns.Length - 1)           
            sql.Append(", ");
      }
      sql.Append(")");
      Cmd.CommandText = sql.ToString();
      Cmd.ExecuteNonQuery();
}

Ответы [ 3 ]

6 голосов
/ 06 февраля 2012

Я давно принял ответ на этот вопрос, но по какой-то причине этого ответа уже нет здесь. Поэтому я думаю, что мне нужно ответить на свой вопрос.

Что я сделал, так это создалкласс parambuilder:

class ParamBuilder
{
    private DbProviderFactory m_factory;
    private DbCommandBuilder m_builder;
    private string m_parameterMarkerFormat;
    public ParamBuilder(DbProviderFactory factory) : this(factory, null)
    {
    }

    public ParamBuilder(DbProviderFactory factory, DbConnection source)
    {
        m_factory = factory;
        m_builder = m_factory.CreateCommandBuilder();
        if (source != null)
        {
            using (DataTable tbl =
                source.GetSchema(DbMetaDataCollectionNames.DataSourceInformation))
            {
                m_parameterMarkerFormat =  
                    tbl.Rows[0][DbMetaDataColumnNames.ParameterMarkerFormat] as string;
            }
        }
        if (String.IsNullOrEmpty(m_parameterMarkerFormat))
            m_parameterMarkerFormat = "{0}";
    }

    public DbParameter CreateParameter(string parameterName, 
        out string parameterMarker)
    {
        DbParameter param = m_factory.CreateParameter();
        param.ParameterName =  
            (string)typeof(DbCommandBuilder).InvokeMember("GetParameterName",
                System.Reflection.BindingFlags.Instance |
                System.Reflection.BindingFlags.InvokeMethod |
                System.Reflection.BindingFlags.NonPublic, null, m_builder, 
                new object[] { parameterName });

        parameterMarker = 
            String.Format(System.Globalization.CultureInfo.InvariantCulture, 
            m_parameterMarkerFormat, param.ParameterName);

        return param;
    }

}

Я создаю переменную-член типа ParamBuilder:

private readonly ParamBuilder m_ParamBuilder;

Затем в методе, где я использую параметры, я использую его следующим образом:

...
string paramMarker;
DbParameter param = m_ParamBuilder.CreateParameter(destination[i].ColumnName, 
    out paramMarker);
sql.Append(paramMarker);

param.Direction = ParameterDirection.Input;
param.Value = source[i];
Cmd.Parameters.Add(param);
...
2 голосов
/ 04 февраля 2012

Создайте абстрактное свойство для получения строки формата, используемой в цикле «values».

class DBOperations
 public abstract string ParameterStringFormat;
 ...
for (int i = 0; i < values.Length; i++)
        {        
            sql.Append(String.Format(ParamterStringFormat, columns[i].ColumnName)); // SQL Server
        }  


class SqlDbOperations : DBOperations
 public override string ParameterStringFormat { get { return "@{0}"; }}


class OracleDBOperations : DBOperations
 public override string ParameterStringFormat { get { return ":{0}"; }}
0 голосов
/ 17 июня 2014

Просто добавьте другой вариант, если хотите быстро и грязно.

string sql = select * from foo there foo.id = @id;
if (isOracle) {
 sql = replaceAll(sql,"@",":");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...