Hallo,
ich nutze NHibernate im ASP.NET-Umfeld (mit MS-SQL Server) und habe ein sehr großes Problem bei gleichzeitigen bzw. mehreren Zugriffen auf die entsprechende Webseite.
Das Problem ist schnell beschrieben (Code und Mapping-Files stehen unten):
Ich habe eine Klasse BusinessModel und eine Klasse BusinessModelProperty. Diese stehen in einer 1:N Beziehung zueinander, eine BusinessModel hat mehrere BusinessModelProperty. Die Beziehung zwischen BusinessModel und BusinessModelProperty ist mit lazy="true" gemappt
Der Fehler äußert sich wie folgt:
Beim Zugriff auf BusinessModel wird in einigen Fällen (abhängig davon , wo sich der User gerade auf der Webseite befindet) auf eine Liste, die die BusinessmodelProperties enthält zugegriffen. Bei meinen Test, die ich alleine mache funktioniert das einwandfrei, aber sobald 5 oder mehr User auf der Seite sind kommt es ab und an zu einer Exception mit der Fehlernmeldung: Failed to lazily initialize a collection. (StackTrace weiter unten)
Hibernate version: 1.2.0
Mapping documents:
Mapping für BusinessModel
Code:
<hibernate-mapping
xmlns="urn:nhibernate-mapping-2.2"
namespace="DatabaseAccess.DatabaseObjects"
assembly="DatabaseAccess">
<class name="BusinessModel" table="BusinessModel">
<meta attribute="field-prefix">m_</meta>
<id name="ID" type="int" unsaved-value="-1">
<column name="ID" sql-type="Int32" not-null="true"/>
<generator class="identity" />
</id>
<!-- einige Properties -->
<many-to-one name="CreditNote"
class="CreditNote"
column="CreditNote"
not-null="false" lazy="false"/>
<many-to-one name="BusinessModelVersion"
class="BusinessModelVersion"
column="Version"
not-null="true" lazy="false"/>
<bag name="BusinessModelProperties" table="BusinessModelProperty" lazy="false" >
<key column="BusinessModelId"/>
<one-to-many class="BusinessModelProperty" />
</bag>
</class>
</hibernate-mapping>
Mapping für BusinessModelProperty
Code:
<hibernate-mapping
xmlns="urn:nhibernate-mapping-2.2"
namespace="DatabaseAccess.DatabaseObjects"
assembly="DatabaseAccess">
<class name="BusinessModelProperty" table="BusinessModelProperty">
<meta attribute="field-prefix">m_</meta>
<id name="ID" type="int" unsaved-value="-1">
<column name="ID" sql-type="Int32" not-null="true"/>
<generator class="identity" />
</id>
<property name="PropertyKey" type="System.String">
<column name="PropertyKey" sql-type="varchar(20)" />
</property>
<property name="PropertyValue" type="StringClob">
<column name="PropertyValue" sql-type="text" />
</property>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():Eine Session wird bei jeder Anfrage neu geöffnet mit:
Code:
public static ISession Session
{
get
{
return m_sessionfactory.OpenSession();
}
}
Geladen wird ein BusinessModel mit:
Code:
public BusinessModel GetBusinessModelByProductName(string productName)
{
BusinessModel result = null;
ISession session = base.Session;
ITransaction ta = session.BeginTransaction();
try
{
IQuery queryBusinessModel =
session.CreateQuery("Select b from BusinessModel as b where b.ProductName=:productName");
queryBusinessModel.SetParameter("productName", productName);
result = (BusinessModel)queryBusinessModel.UniqueResult();
ta.Commit();
}
catch (ObjectNotFoundException objnfex)
{
ta.Rollback();
// Handling der Exception
}
catch (Exception ex)
{
ta.Rollback();
// Handling der Exception
}
finally
{
session.Flush();
}
return result;
}
Full stack trace of any exception that occurs:
Es gibt verschiedenste Fehlermeldungen, aber eine taucht immer wieder auf:
NHibernate.ADOException: could not initialize a collection: [DatabaseAccess.DatabaseObjects.BusinessModel.BusinessModelProperties#87][SQL: SELECT businessmo0_.BusinessModelId as Business4___1_, businessmo0_.ID as ID1_, businessmo0_.ID as ID32_0_, businessmo0_.PropertyKey as Property2_32_0_, businessmo0_.PropertyValue as Property3_32_0_, businessmo0_.BusinessModelId as Business4_32_0_ FROM BusinessModelProperty businessmo0_ WHERE businessmo0_.BusinessModelId=?] ---> System.InvalidOperationException: Diesem Befehl ist bereits ein geöffneter DataReader zugeordnet, der zuerst geschlossen werden muss.
bei System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command)
bei System.Data.SqlClient.SqlConnection.ValidateConnectionForExecute(String method, SqlCommand command)
bei System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async)
bei System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
bei System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
bei System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
bei System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
bei System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader()
bei NHibernate.Impl.BatcherImpl.ExecuteReader(IDbCommand cmd)
bei NHibernate.Loader.Loader.GetResultSet(IDbCommand st, RowSelection selection, ISessionImplementor session)
bei NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
bei NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
bei NHibernate.Loader.Loader.LoadCollect
Name and version of the database you are using:
MS-SQL Server 2000
Debug level Hibernate log excerpt:
ERROR
Ich bin für jede Hilfe dankbar
rijn