2011-02-21 3 views
1

В моем многоуровневом приложении уровень доступа к данным считывает базу данных и возвращает SqlDataReader для коллекций объектов и SqlDataRecord для одного объекта для бизнес-уровня. Бизнес-уровень имеет конструкторы, которые инициализируют SqlDataReader или SqlDataRecord. Это казалось естественным дизайном, но я столкнулся с множеством проблем, когда читатели выходили из сферы действия и несколько одновременных читателей. Каков лучший способ справиться с этим дизайном? Лучше ли заставить слой данных возвращать словарь полей и немедленно удалять читателей? И лучше ли использовать DataSets, где потоковая передача данных не требуется?Проблемы с многоуровневым дизайном при использовании ADO.NET

Некоторые примеры исключений, с которыми я сталкиваюсь в моем приложении:
- Invalid attempt to call MetaData when reader is closed
- There is already an open DataReader associated with this Command which must be closed first

EDIT: нашел отличную статью Contrasting the ADO.NET DataReader and DataSet. При необходимости использовать DataSets (отключенный, буферизованный подход).

ответ

1

Вы обязательно хотите как можно скорее закрыть соединения SqlDataReader. SqlDataReader работает очень быстро, но когда они остаются открытыми, вы используете одно из подключений пула соединений. Это может легко привести вас в состояние, в котором у вас есть проблемы с ресурсами, как вы упомянули.

Я бы не предложил, по вашему мнению, передать SqlDataReader в бизнес-уровень. Я бы либо заполнил DataSet и передал это, либо создал объект пользовательских объектов данных и вернул его в бизнес-уровень.

1

Почему бы не возвращать классы из вашего DAL? Это могут быть либо бизнес-объекты, либо классы, на которые вы передаете данные непосредственно в DAL, а затем на бизнес-объекты, и в этом случае может оказаться полезным AutoMapper.

Исключения действительно выглядят как проблемы дизайна для меня. Второй может быть решен using MARS, хотя я рекомендую сначала рассмотреть другие варианты - вы должны как можно скорее закрыть DataReaders/connections и т. Д.

Mapping на Pocos имеет дополнительный вариант, который вы легко перейти на другие технологии доступа к данным, как LINQ к SQL, NHibernate, Entity Framework и т.д.

популярного подход thesedays является использование repository pattern.

1

Вы загрязняете свой бизнес-уровень, позволяя ему работать с классами ADO.NET. Инкапсулируйте свой код «Sql *» полностью на уровне базы данных и используйте операции CRUD для управления обновлениями/вставками.

class BusinessObject 
{ 
    public BusinessData GetBusinessData() 
    { 
     //... 
     DataSet ds = DatabaseLayer.GetData(businessObjParams); 
     return new BusinessData(ds); 
    } 
} 

static class DatabaseLayer 
{ 
    public DataSet GetData(BusinessParams params) 
    { 
     //... open your connection, get the data, fill DataSet. 
     //... close connection 
     return dataSet; 
    } 
} 
+0

так что вы в основном предлагаете то, что уже сделал Брэди, используйте DataSets вместо классов ADO.NET. Правильно? – kateroh

+0

Да, @ Бради говорит вам то же самое, что и я. Используйте DataSets или свой собственный тип данных и строго соблюдайте SQL-запросы (объекты и классы) на уровне базы данных. Обратите внимание, что DataSet не является частью ADO.NET. –

+0

Другой ответ от @RichardOD также предлагает то же самое и многое другое. –

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