Frågan 26 juni 2008 12:36 #1 Ett skumt fel har uppstått!
Map fil:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Entities.Log, Entities" table="Logs">
<id name="Id" column="LogID" type="int" unsaved-value="0">
<generator class="identity" />
</id>
<property name="Category" column="Category" type="String" />
<property name="Source" column="Source" type="String"/>
<property name="Description" column="Description" type="String"/>
<property name="User" column="[User]" type="String"/>
<property name="Ip" column="Ip" type="String"/>
<property name="CreateDate" column="CreateDate" type="DateTime" />
<property name="SiteName" column="SiteName" type="String"/>
</class>
</hibernate-mapping>
Sparar objekt:
Entities.Log log = new Entities.Log();
log.Category = "LOGIN";
log.Source = "";
log.Description = "Loggade in";
log.SiteName = site.Name;
log.User = user.Profile.FirstName + " " + user.Profile.LastName;
log.Ip = Request.UserHostAddress;
log.CreateDate = DateTime.Now;
LogDao.Save(log);
Denna kod funkar "typ" som den ska, objektet log sparas som den ska till databasen.
Men:
I samma skede som loggen sparas så spar NHibernate även objektet Site!
Hur kan det komma sig när log inte har någon relation alls till site?
Vad händer i LogDao.Save()?
Kan det vara så att ett anrop till session.Flush() utförs?
Saven ser ut så här:
public dbReturnValues Save(T objectToSave)
{
dbReturnValues retVal = new dbReturnValues();
ITransaction tx = null;
try
{
tx = NHibernateHelper.GetCurrentSession().BeginTransaction();
NHibernateHelper.GetCurrentSession().Save(objectToSave);
tx.Commit();
retVal.Success = true;
}
catch (Exception ex)
{
if (tx != null)
tx.Rollback();
throw new Exception(ex.Message);
}
finally
{
tx.Dispose();
}
return retVal;
}
Jag har inte specat en Flush någon annanstans i koden heller.
Gör NHibernate en intern Flush automatiskt när den stängs eller vid annat tillfälle?
Vad jag förstår av dokumentationen så körs en Flush vid transaction.Commit().
Lite off-topic, du bör se över din felhantering.
try
{
tx = NHibernateHelper.GetCurrentSession().BeginTransaction();
NHibernateHelper.GetCurrentSession().Save(objectToSave);
tx.Commit();
retVal.Success = true;
}
catch (Exception ex)
{
if (tx != null)
tx.Rollback();
throw new Exception(ex.Message);
}
Kör en rethrow istället för att skapa en ny instans av exception.
skriv enbart throw;
try
{
tx = NHibernateHelper.GetCurrentSession().BeginTransaction();
NHibernateHelper.GetCurrentSession().Save(objectToSave);
tx.Commit();
retVal.Success = true;
}
catch (Exception)
{
if (tx != null)
tx.Rollback();
throw;
}
Ahh, så klart. Tack för tipset! :)
Jag hittade på stycket om Flush och det är som du skriver, vid transaction.Commit() som den flushar.
Det finns dock FlushMode att ställa in, frågan är om man vågar sätta den till Never? Vilka konsekvenser kan det få?
NHibernate hjälpfil skrev:
It is possible to change the default behavior so that flush occurs less frequently. The FlushMode class defines three different modes: only flush at commit time (and only when the NHibernate ITransaction API is used), flush automatically using the explained routine, or never flush unless Flush() is called explicitly. The last mode is useful for long running units of work, where an ISession is kept open and disconnected for a long time
spango Medlem sedan juni 2000 8 205 inlägg
Nickemannen skrev:
Kör en rethrow istället för att skapa en ny instans av exception.
skriv enbart throw;
Just i det här fallet är det ännu enklare eftersom transaktioner är disposable:
using (var tx = NHibernateHelper.GetCurrentSession().BeginTransaction();)
{
NHibernateHelper.GetCurrentSession().Save(objectToSave);
tx.Commit();
retVal.Success = true;
}
Och flukta in http://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html/manipulatingdata.html#manipulatingdata-exceptions
Har jag fattat rätt om att jag kan skriva så här då?
public dbReturnValues Save(T objectToSave)
{
dbReturnValues retVal = new dbReturnValues();
using (var tx = NHibernateHelper.GetCurrentSession().BeginTransaction())
{
NHibernateHelper.GetCurrentSession().Save(objectToSave);
tx.Commit();
retVal.Success = true;
}
return retVal;
}
Alltså helt utan try,catch?
spango Medlem sedan juni 2000 8 205 inlägg Ja, det blir ekvivalent med:
public dbReturnValues Save(T objectToSave)
{
dbReturnValues retVal = new dbReturnValues();
var tx = NHibernateHelper.GetCurrentSession().BeginTransaction();
try
{
NHibernateHelper.GetCurrentSession().Save(objectToSave);
tx.Commit();
retVal.Success = true;
}
finally
{
tx.Dispose();
}
return retVal;
}