5

我的网站使用的是企业库 v 5.0。主要是DAAB。executescalar、executedataset 等一些函数按预期工作。开始使用 Readers 时出现的问题

我的包含类中有这个功能:

Public Function AssignedDepartmentDetail(ByVal Did As Integer) As SqlDataReader
    Dim reader As SqlDataReader
    Dim Command As SqlCommand = db.GetSqlStringCommand("select seomthing from somewhere where something = @did")
    db.AddInParameter(Command, "@did", Data.DbType.Int32, Did)
    reader = db.ExecuteReader(Command)
    reader.Read()
    Return reader
End Function

这是从我的 aspx.vb 调用的,如下所示:

reader = includes.AssignedDepartmentDetail(Did)
If reader.HasRows Then
    TheModule = reader("templatefilename")
    PageID = reader("id")
Else
    TheModule = "#"
End If

这会在 db.ExecuteReader 行出现以下错误:

无法将“Microsoft.Practices.EnterpriseLibrary.Data.RefCountingDataReader”类型的对象转换为“System.Data.SqlClient.SqlDataReader”类型。

任何人都可以阐明我如何开始这项工作。通过 entlib 与读者打交道时,我是否总是会遇到问题?

4

6 回答 6

3

我会小心这个实现。Enterprise Library Codeplex 网站上有一个线程解释了这个的背景: http ://entlib.codeplex.com/Thread/View.aspx?ThreadId=212973

Chris Tavares 解释说只返回 .InnerReader 是不好的,因为这样会取消 Enterprise Library 的连接跟踪(他在 5 月 20 日下午 5:39 的回复):“这种方法会彻底搞砸你的连接管理。整个使用包装器的原因是我们可以在处理时执行额外的代码来清理东西。抓住内部阅读器并丢弃外部阅读器会泄漏连接!”

所以是的,这有点痛苦,我们处于同样的情况。

问候,迈克

于 2010-06-15T19:29:41.770 回答
1

Enterprise Library 中的 ExecuteReader 将 IDataReader 包装到 RefCountingDataReader 中,作为 SqlDataReader 实现 IDataReader 接口。

RefCountingDataReader 具有可以转换为 SqlDataReader 的 InnerReader 属性。下面的示例使用 C# 编写,但您可以轻松地将其转换为 VB.NET。

SqlDataReader reader;
reader = ((RefCountingDataReader)db.ExecuteReader(command)).InnerReader as SqlDataReader;
if (reader != null)
    reader.Read();
return reader;

希望能帮助到你

于 2010-05-20T14:38:55.657 回答
1

我有泄漏连接,因为我所有的 DA 方法都需要 SqlDataReader。现在我必须返回内部 RefCountingDataReader 并且永远无法关闭外部阅读器。旧的企业库在返回 SqlDataReader 时运行良好。

于 2010-08-13T03:53:03.813 回答
1

我已经考虑了 ctavars 在http://entlib.codeplex.com/discussions/212973http://entlib.codeplex.com/discussions/211288上发布的评论和代码,从而得出以下通用方法来获取SQL 数据阅读器。

通常,您IDataReader在 using 语句中使用,然后尽可能直接使用该引用。AsSqlDataReader当您需要特定于 SQL 的东西时调用它。

在某处添加此扩展类:

/// <summary>
/// Obtains an <see cref="SqlDataReader"/> from less derived data readers in Enterprise Library
/// </summary>
/// <remarks>
/// See http://entlib.codeplex.com/discussions/212973 and http://entlib.codeplex.com/discussions/211288
/// for a discussion of why this is necessary
/// </remarks>
public static class SqlDataReaderExtension
{
    /// <summary>
    /// Allows the internal <see cref="SqlDataReader"/> of a <see cref="RefCountingDataReader"/> to be accessed safely
    /// </summary>
    /// <remarks>
    /// To ensure correct use, the returned reference must not be retained and used outside the scope of the input
    /// reference. This is so that the reference counting does not get broken. In practice this means calling this method
    /// on the base reader every time a reference to it is required.
    /// </remarks>
    public static SqlDataReader AsSqlDataReader(this RefCountingDataReader reader)
    {
        return (SqlDataReader)(reader.InnerReader);
    }

    /// <summary>
    /// Allows the internal <see cref="SqlDataReader"/> of a <see cref="IDataReader"/> to be accessed safely
    /// </summary>
    /// <remarks>
    /// To ensure correct use, the returned reference must not be retained and used outside the scope of the input
    /// reference. This is so that the reference counting does not get broken. In practice this means calling this method
    /// on the base reader every time a reference to it is required.
    /// </remarks>
    public static SqlDataReader AsSqlDataReader(this IDataReader reader)
    {
        return (SqlDataReader)(((RefCountingDataReader)(reader)).InnerReader);
    }
}

...然后要使用 SQLReader 读取数据,请执行以下操作:

using (IDataReader reader = db.ExecuteReader(command))
{
    while (reader.Read())
    {
        reader.GetInt32(reader.GetOrdinal("SomeColumn")),
        reader.GetInt32(reader.GetOrdinal("SomeOtherColumn")),
        reader.GetInt32(reader.GetOrdinal("SomeFurtherColumn")),
        // Obtain the SQL data reader each time it is used
        // (Note that GetDateTimeOffset is not on the standard IDataReader)
        reader.AsSqlDataReader().GetDateTimeOffset(reader.GetOrdinal("SQLSpecificColumn"))
        reader.AsSqlDataReader().GetDateTimeOffset(reader.GetOrdinal("AnotherSQLSpecificColumn"))
        reader.GetString(reader.GetOrdinal("SomeAdditionalColumn"))
    }
}
于 2013-07-29T19:09:18.590 回答
0

我想我有一个可行的解决方案。

enter code here

    ' Create the Database object, using the default database service. The
    ' default database service is determined through configuration.
    Dim db As Microsoft.Practices.EnterpriseLibrary.Data.Database = EnterpriseLibraryContainer.Current.GetInstance(Of Microsoft.Practices.EnterpriseLibrary.Data.Database)(DatabaseName)

    Dim dbCommand As DbCommand
    dbCommand = db.GetStoredProcCommand(StoredProcedureName)

    'create a new database connection based on the enterprise library database connection
    Dim dbConnection As System.Data.Common.DbConnection
    dbConnection = db.CreateConnection
    dbConnection.Open()

    'set the dbCommand equal to the open dbConnection
    dbCommand.Connection = dbConnection

    'return a ADO sqlDatareader but still managed by the EnterpriseLibrary
    Return dbCommand.ExecuteReader(CommandBehavior.CloseConnection)
于 2010-08-16T01:32:34.030 回答
0

您应该使用接口,而不是具体类。

Public Function AssignedDepartmentDetail(ByVal Did As Integer) As IDataReader
    Dim reader As IDataReader
    Dim Command As SqlCommand = db.GetSqlStringCommand("select seomthing from somewhere where something = @did")
    db.AddInParameter(Command, "@did", Data.DbType.Int32, Did)
    reader = db.ExecuteReader(Command)
    reader.Read()
    Return reader
End Function

和用法。就个人而言,我永远不会在表示层页面中使用数据阅读器,但我猜对每个人都是他/她自己的。

Private Const TemplateFileName_Select_Column_Ordinal As Integer = 0
Private Const Id_Select_Column_Ordinal As Integer = 1

Private Sub DoSomething()
dim reader as IDataReader
reader = includes.AssignedDepartmentDetail(Did)
If reader.HasRows Then
    TheModule = reader(TemplateFileName_Select_Column_Ordinal)
    PageID = reader(Id_Select_Column_Ordinal)
Else
    TheModule = "#"

    reader.Close()  ''Dude, close your reader(s)

End If
于 2012-07-31T17:42:43.843 回答