2010-04-23 2 views
8

У меня есть бизнес-уровня, который проходит строку Конн и SQLCommand на уровне данных, как такМожно ли передать SQLCommand в качестве параметра?

public void PopulateLocalData() 
    { 
     System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(); 
     cmd.CommandType = System.Data.CommandType.StoredProcedure; 
     cmd.CommandText = "usp_PopulateServiceSurveyLocal"; 
     DataLayer.DataProvider.ExecSQL(ConnString, cmd); 
    } 

DataLayer затем просто выполняет SQL, как так

 public static int ExecSQL(string sqlConnString, System.Data.SqlClient.SqlCommand cmd) 
    { 
     int rowsAffected; 
     using (SqlConnection conn = new SqlConnection(sqlConnString)) 
     { 
      conn.Open(); 
      cmd.Connection = conn; 
      rowsAffected = cmd.ExecuteNonQuery(); 
      cmd.Dispose(); 
     } 
     return rowsAffected; 
    } 

Это нормально для меня передайте SQLCommand в качестве параметра, подобного этому, или есть более приемлемый способ его выполнения. Одна из моих проблем заключается в возникновении ошибки при выполнении запроса, когда строка cmd.dispose никогда не будет выполнена. Означает ли это, что он будет продолжать использовать память, которая никогда не будет выпущена?

Update:

Следуя совету Эрика я более четко разделил бизнес и данных слоев, поэтому метод в бизнес-слой выглядит следующим образом

public void PopulateLocalData() 
    { 
     DataLayer Data = new DataLayer(this.ConnString); 
     Data.UpdateLocalData(); 
    } 

и метод, который вызывается в DataLayer выглядит следующим образом ,

 public void UpdateLocalData() 
    { 
     using (SqlConnection conn = new SqlConnection(this.ConnString)) 
     using(SqlCommand cmd = new SqlCommand()) 
     { 
      cmd.CommandType = System.Data.CommandType.StoredProcedure; 
      cmd.CommandText = "usp_PopulateServiceSurveyLocal"; 
      conn.Open(); 
      cmd.Connection = conn; 
      cmd.ExecuteNonQuery(); 
     } 
    } 

Таким образом, очень ясно, что и SQLCommand, и SQLConnection будут утилизированы должным образом. Благодарю.

ответ

6

В идеале ваш бизнес-уровень не должен знать о деталях реализации вашего уровня данных. Итак, реализуете ли вы уровень данных с объектами SqlCommand или с чем-то вроде NHibernate, должны быть неактуальны для бизнес-уровня. Это делает теоретически легко «сдвинуть» ваш уровень данных и заменить его другим.

Подведение итогов: передача SqlCommand от бизнес-уровня до уровня данных в моих глазах не считается хорошей практикой.

Относительно Dispose(): если вы используете с помощью-заявление (как using(SqlConnection ...)), метод Dispose() вызывается автоматически в конце с помощью заявления. Вам не нужно делать это вручную.

+0

. Нельзя использовать (SqlCommand ...), хотя ... и проблема в том, что команда не может быть утилизирована должным образом, если что-то не удается. Соединение прекрасное. – cHao

+0

Насколько я знаю, использование (SqlCommand cmd = ...) вполне допустимо. –

-1

Ну для начала, вы можете изменить его на:

public static int ExecSQL(string sqlConnString, System.Data.SqlClient.SqlCommand cmd) 
{ 
    int rowsAffected; 
    try 
    { 
     using (SqlConnection conn = new SqlConnection(sqlConnString)) 
     { 
      conn.Open(); 
      cmd.Connection = conn; 
      rowsAffected = cmd.ExecuteNonQuery(); 
     } 
    } finally { 
     cmd.Dispose(); 
    } 
    return rowsAffected; 
} 

Кроме того, я вообще отделить мой бизнес и данные, слои больше, чем вы. Мой бизнес-уровень вызовет метод «GetLocalSurvey» в слое данных, который будет обрабатывать всю глупость SQL.

0

Почему вы не изменить его к этому:

public static int ExecProcedure(string sqlConnString, string procedureName) 
{ 
    using (var cmd = new System.Data.SqlClient.SqlCommand()) 
    { 
     cmd.CommandType = System.Data.CommandType.StoredProcedure; 
     cmd.CommandText = procedureName; 
     int rowsAffected; 
     using (SqlConnection conn = new SqlConnection(sqlConnString)) 
     { 
      conn.Open(); 
      cmd.Connection = conn; 
      return cmd.ExecuteNonQuery(); 
     } 
    } 
} 

Вы хотите дополнительные параметры? Создание перегрузок, рефакторинг. Поделитесь большинством кода в общей функции. Создание new System.Data.SqlClient.SqlCommand() везде - неправильный подход.

0

Создающий команду должен нести ответственность за ее удаление. Самый простой способ для этого, чтобы удалить вызов cmd.Dispose из ExecSql и вместо того, чтобы позвонить вашей функции как это:

public void PopulateLocalData() 
{ 
    using (System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand()) 
    { 
     cmd.CommandType = System.Data.CommandType.StoredProcedure; 
     cmd.CommandText = "usp_PopulateServiceSurveyLocal"; 
     DataLayer.DataProvider.ExecSQL(ConnString, cmd); 
    } 
} 

Одна из моих проблем, если возникает ошибка при выполнении запроса cmd.dispose линии никогда не выполняйте.Означает ли это, что он будет продолжать использовать память, которая никогда не будет выпущена?

По совпадению, SqlClient.SqlCommand не нужно удалять. Это, однако, является деталью реализации, что вы не должны полагаться на - общее правило еще: если он реализует IDisposable, утилизировать его (SqlCeClient.SqlCeCommand, например, делает нужно утилизировать ...)

Смежные вопросы