Gussfehler auf SQLDataReader
-
03-10-2019 - |
Frage
Meine Website wird mit Enterprise Library v 5.0. Vor allem der DAAB. Einige Funktionen wie ExecuteScalar, ExecuteDataset arbeiten wie erwartet. Die Probleme auftreten, wenn ich auf den Einsatz Leser
startenIch habe diese Funktion in meiner enthält Klasse:
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
Dies ist aus meiner aspx.vb wie so genannt:
reader = includes.AssignedDepartmentDetail(Did)
If reader.HasRows Then
TheModule = reader("templatefilename")
PageID = reader("id")
Else
TheModule = "#"
End If
Dies gibt die folgenden Fehler auf db.ExecuteReader Zeile:
Kann nicht Gussobjekt des Typs 'Microsoft.Practices.EnterpriseLibrary.Data.RefCountingDataReader' eingeben 'System.Data.SqlClient.SqlDataReader'.
Schuppen Kann jemand irgendein Licht auf, wie ich mich über diese Arbeit zu bekommen. Werde ich immer auf Probleme stoßen, wenn sie mit Lesern über EntLib zu tun?
Lösung
Ich glaube, ich habe eine funktionierende Lösung.
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)
Andere Tipps
würde ich mit dieser Implementierung vorsichtig sein. Es ist ein Thread auf der Enterprise Library Codeplex-Site, die die backgound für das erklärt: http://entlib.codeplex.com/Thread/View.aspx?ThreadId= 212973
Chris Tavares erklärt, dass es nicht gut ist, nur die .InnerReader zurückkehren, weil dann die Verbindung von Enterprise Library Tracking abgeworfen (seine Antwort vom 20. Mai, 17.39 Uhr): „Dieser Ansatz wird vollständig schrauben Sie Ihre Verbindung Verwaltung. Der ganze Grund für die Umhüllung so ist, dass wir zusätzlichen Code sauber Sachen zu entsorgen Zeit bis ausführen kann. Die innere Leser Grabbing und die äußere werfen leckt Verbindungen! „
Also ja, das ist ein bisschen wie ein Schmerz zu behandeln, die wir in der gleichen Situation sind.
Viele Grüße, Mike
ExecuteReader in Enterprise Library hüllt IDataReader in RefCountingDataReader dass als SqlDataReader Geräte IDataReader Schnittstelle.
RefCountingDataReader hat InnerReader Eigenschaft, die Sie SqlDataReader werfen können. Das folgende Beispiel ist in C #, aber Sie können es zu VB.NET leicht umwandeln.
SqlDataReader reader;
reader = ((RefCountingDataReader)db.ExecuteReader(command)).InnerReader as SqlDataReader;
if (reader != null)
reader.Read();
return reader;
Hope es hilft
Ich habe Verbindungen undicht, weil alle meine DA Methoden einen SqlDataReader erfordern. Jetzt muß ich die inneren RefCountingDataReader zurückkehren und kann niemals den äußeren Leser schließen. Die alte Enterprise Library funktioniert gut mit einem SqlDataReader zurück.
Ich habe berücksichtigt die Kommentare und Code von ctavars veröffentlicht unter http: //entlib.codeplex. com / Diskussionen / 212973 und http://entlib.codeplex.com/discussions/211288 in dem folgenden generischen Ansatz führt, das ein SQL-Datenleser zu erhalten.
Generell Sie IDataReader
in der using-Anweisung verwenden, verwenden Sie dann, dass der Bezug direkt, wenn Sie können. Rufen Sie AsSqlDataReader
auf es, wenn Sie brauchen etwas SQL-spezifisch ist.
Fügen Sie diese Erweiterung Klasse irgendwo:
/// <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);
}
}
... dann Daten mit einem SQLReader zu lesen, etwas tun, wie folgt aus:
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"))
}
}
Sie sollten die Schnittstelle verwenden, nicht die konkrete Klasse.
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
und die Nutzung. Persönlich würde ich nie eine Datareader in einer Präsentationsschicht-Seite verwenden, aber zu jeder seine / ihre eigenen, denke ich.
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