在我的多层应用程序中,数据访问层读取数据库并将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(断开连接,缓冲方法)。
答案 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;
}
}