使用ADO.NET时出现多层设计问题

时间:2011-02-21 21:58:20

标签: sql sql-server ado.net

在我的多层应用程序中,数据访问层读取数据库并将SqlDataReader返回给对象集合,并将单个对象的SqlDataRecord返回给业务层。业务层具有初始化SqlDataReader或SqlDataRecord的构造函数。这似乎是一个自然的设计,但是我遇到了读者超出范围和多个并发读者的多个问题。有什么更好的方法来解决这个问题?是否更好地使数据层返回字段字典并立即处理读者?在不需要数据流传输的地方使用DataSet是否更好?

我在应用程序中遇到的一些例外情况:
- Invalid attempt to call MetaData when reader is closed
- There is already an open DataReader associated with this Command which must be closed first

编辑:找到了一篇优秀文章Contrasting the ADO.NET DataReader and DataSet。在适当的时候使用DataSet(断开连接,缓冲方法)。

3 个答案:

答案 0 :(得分:1)

您肯定希望尽快关闭SqlDataReader连接。 SqlDataReader非常快,但是当它们保持打开状态时,您正在使用其中一个连接池连接。如您所述,这可能很容易让您陷入资源问题。

我不会像你的建议那样将SqlDataReader传递给业务层。我要么填满一个DataSet并传递它,要么构造一个自定义数据实体对象并将其返回给业务层。

答案 1 :(得分:1)

为什么不从DAL返回课程?这些可以是业务对象,也可以是将数据直接映射到DAL,然后映射到业务对象的类,在这种情况下AutoMapper可能有用。

这些例外对我来说真的像设计问题。第二个可以解决using MARS,但我建议你先考虑其他选项 - 你应该尽快关闭DataReaders / connections等。

映射到POCO后添加了一个选项,您可以轻松切换到其他数据访问技术,如LINQ to SQL,NHibernate,Entity Framework等。

一种流行的方法是使用repository pattern

答案 2 :(得分: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;
   }
}