2009-07-12 3 views
2

Я был назначен в проекте, где DAL состоит из базового класса с функциями для возврата IDataReader, Object (int, string и т. П.) Или DataSet. Также существует функция ExecuteNonQuery. Этот DAL только обращается к USPs (SQL Server) и использует SqlHelper для выполнения запросов. Вот две функции выборки из базы:Устранение SqlConnection из базового класса DAL при вызове ExecuteReader

protected IDataReader ExecuteReader(string storedProcedure, params object[] parameterValues) 
    { 
     SqlConnection HConnection = new SqlConnection(myConnString); 
     IDataReader ret = null; 
     try 
     { 
      ret = SqlHelper.ExecuteReader(HConnection, storedProcedure, parameterValues); 
     } 
     catch (Exception ex) 
     { 
      HanldeError(ex, storedProcedure, parameterValues); 
     } 
     return ret; 
    } 

    protected object ExecuteScalar(string storedProcedure, params object[] parameterValues) 
    { 
     using (SqlConnection HConnection = new SqlConnection(myConnString)) 
     { 
      object ret = null; 
      try 
      { 
       ret = SqlHelper.ExecuteScalar(HConnection, storedProcedure, parameterValues); 
      } 
      catch (Exception ex) 
      { 
       HanldeError(ex, storedProcedure, parameterValues); 
      } 
      return ret; 
     } 
    } 

Другие классы вытекают из этого базового класса, создавая конкретные задачи DAL классов, например:

public class Orders : BaseDal { 
    public IDataReader GetOrdersList(int clientId, int agentId) 
    { 
     return ExecuteReader("usp_Orders_GetOrdersList", clientId, agentId); 
    } 
    ... 
} 

Тогда существуют классы BLL, которые вызывают функции DAL и заполнить объекты (например, объект Order) с данными, на основе данных, считанных из IDataReader объекта:

public Order[] GetOrdersList(int ClientIDX, int AgentIDX) 
    { 
     List<Order> ret = null; 
     using (IDataReader dr = objDAL.GetOrdersList(ClientIDX, AgentIDX)) 
     { 
      if (dr != null) 
      { 
       ret = new List<Order>(); 
       while (dr.Read()) 
       { 
        ret.Add(xReadOrder(dr, 0)); 
       } 
      } 
     } 
     return ret.ToArray(); 
    } 

Мой вопрос заключается в следующем - если вы посмотрите на код, принятых из BaseDal вы заметите, что только ExecuteScalar фактически завершает объект SqlConnection (оператор using) - так обстоит дело со всеми моими функциями. С ExecuteReader я не могу этого сделать, поскольку я возвращаю открытый объект SqlDataReader и закрытие соединения приведет к недействительности читателя. У меня есть весь код, получающий и использующий IDataReader из DAL, используя инструкцию using, но также находится объект SqlConnection, или он GC на поздней стадии, причиняя вред пулу соединений, не освобождая его раньше? Если да, то как это можно лечить?

Кроме того, существует ли лучший подход к созданию DAL, чем описанный выше? Меня меньше интересует агностик данных DAL, нам нужен только прочный и простой в обслуживании, который может принимать много одновременных соединений из многих потоков.

Заранее благодарим за помощь.

ответ

4

SqlDataReader будет закрывать соединение, если вы укажете CommandBehavior.CloseConnection при выполнении команды. Тем не менее, он чувствует себя немного уродливым в любом случае.

Вместо этого передайте SqlConnectionв метод и используйте это. Тогда вызывающий имеет контроль над тем, когда он находится. В качестве альтернативы возьмите Action<SqlDataReader> для выполнения с открытым считывателем и сделайте метод закрытым как для чтения, так и для соединения после выполнения действия. Разумеется, это действие должно было бы сделать все, что нужно для читателя.

+0

Спасибо. Хотя вы считаете это «уродливым», использование 'CommandBehavior.CloseConnection' похоже на мой лучший вариант, поскольку это то, что SqlHelper делает внутренне, когда передается строка соединения (в отличие от объекта' SqlConnection'). Передача 'SqlConnection' в метод не является вариантом, так как это будет противоречить разделению DAL/BLL, которое я пытаюсь сохранить. Подход «Action », с которым я не знаком, но, похоже, это немного больно. Просто чтобы убедиться - можете ли вы указать мне на хорошее место, чтобы на самом деле увидеть, что это значит? – synhershko

+0

Ум, не легко (я в середине пытаюсь что-то исправить), но вы должны использовать выражение лямбда, чтобы сказать «когда у вас открыт читатель, вот что я хочу с ним делать» в основном , –

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