0

Я пытаюсь создать «общий» метод на уровне доступа к данным, который выполняет переданную хранимую процедуру на Sql Server, а также принимает список/массив/набор SqlParameters, чтобы использовать вызов хранимой процедуры в другом части кода легче (без необходимости ухода за соединением, командами и т. д.).Общий способ выполнения процедуры для DAL, вкл. Параметры

Целью является а. например:

int iAffectedRows = dal.RunProcedure("dbo.mySP", parameters); 

Параметры, конечно, должны быть определены ранее, но без типов. Я хочу, чтобы они были созданы с использованием метода AddwithValue()SqlParameterCollection class.

Похоже, это невозможно, потому что класс SqlParameterCollection не может быть инстанцирован. Посмотрите на это discussion.

Кто-нибудь знает, как это создать?

ответ

1

Не стоит посылать DbParameterCollection (SqlParameterCollection), так как он тесно связан (который вы обнаружили) с инфраструктурой ADO.NET, которую вы пытаетесь отвлечь. Лучше сопоставить собственное представление параметров с коллекцией внутри вашего метода.

Вы можете решить, используя что-то вроде этого:

public class DataAccess 
{ 
    private ConnectionStringSettings _settings; 

    public DataAccess(ConnectionStringSettings settings) 
    { 
     _settings = settings; 
    } 

    public int RunProcedure(string name, dynamic parameters) 
    { 
     using (var conn = CreateConnection()) 
     using (var command = CreateCommand(conn, name, parameters)) 
     { 
      return command.ExecuteNonQuery(); 
     } 
    } 

    private DbConnection CreateConnection() 
    { 
     var factory = DbProviderFactories.GetFactory(_settings.ProviderName); 
     var connection = factory.CreateConnection(); 
     connection.ConnectionString = _settings.ConnectionString; 
     connection.Open(); 
     return connection; 
    } 

    private DbCommand CreateCommand(DbConnection conn, string commandText, 
     object parameters) 
    { 
     var cmd = conn.CreateCommand(); 
     cmd.CommandText = commandText; 
     cmd.CommandType = CommandType.StoredProcedure; 
     foreach(PropertyInfo parameter in parameters.GetType().GetProperties()) 
     { 
      var commandParameter = cmd.CreateParameter(); 
      commandParameter.ParameterName = "@" + parameter.Name; 
      commandParameter.Value = parameter.GetValue(parameters); 
      cmd.Parameters.Add(commandParameter); 
     } 
     return cmd; 
    } 
} 

Callable с синтаксисом, как это:

dal.RunProcedure("dbo.mySP", new { 
    Parameter1 = value1, 
    Parameter2 = value2 
}); 

Вы можете значительно упростить код, если вы хотите, чтобы поддержать SqlClient.

Но вместо того, чтобы катать это самостоятельно, используйте готовые стабильные библиотеки, такие как Dapper.

+0

'PropertyInfo' доступен в' System.Reflection'. Добавьте 'using System.Reflection'' к вашему коду. – PHeiberg

+0

Да, извините, я не осознал Отражения. Но метод GetValue() все еще не допускает только одного аргумента. – Magier

+1

Если вы используете .NET 2.0, то перегрузки, которую я использовал, там нет, и вы должны передать дополнительный параметр 'GetValue' -' parameter.GetValue (parameters, null) '. – PHeiberg

0

Я кончался следующим раствором:

SqlParameter[] parameters = { 
new SqlParameter("@p1", SqlDbType.Int) { Value = 999}, 
new SqlParameter("@p2", SqlDbType.Char, 30, "source") { Value = "test"} 
}; 
da.RunProcedure("[dbo].[SP1]", parameters, out rowsAffected); 

RunProcedure принимает IDataParameter[] parameters и направляет это к способу строителя команды, который добавляет каждый сингл из них в SqlParameters собственность моего SqlCommand объекта:

private static SqlCommand BuildQueryCommand(string storedProcName, IDataParameter[] parameters) 
     { 
      SqlCommand command = new SqlCommand(storedProcName, GetDBConnection()); 
      command.CommandType = CommandType.StoredProcedure; 

      if (parameters != null) 
      { 
       foreach (SqlParameter parameter in parameters) 
       { 
        command.Parameters.Add(parameter); 
       } 
      } 
      return command;  
     } 

Это прекрасно работает, и таким образом я могу добавить каждый Парам с одной единственной строкой кода (это был мой пункт назначения № 1), вкл. все свойства SqlParameter доступны (при необходимости используйте SqlDBType, это зависит от пользователя).