안녕하세요 여러분, 여기 내 머리를 감싸는 데 약간의 문제가 있습니다.Log4Net을 통한 nHibernate 로깅, 세션 세션 문제
저는 현재 nHibernate로 시작하고 있습니다. 작업 요구 사항에 따라야하고, nHibernate의 세션과 다중 스레드에 조금 붙어 있습니다. Log4Net에서 nHibernate의 디버그/오류 등을 포함한 모든 것을 Logging 할 필요가있다.
그래서 내가 한 것은 매우 간단한 Log4Net : AppenderSkeleton 클래스를 필요로 할 때 완벽하게 생성한다. 내가 직면 한 나의 초기 문제는 GetCurrentSession을 사용했을 때 분명히 Log4Net이 별도의 스레드에서 실행되기 때문에 초기 스레드의 세션에서 오류가 발생했다는 것입니다. 그래서 Log4Net AppenderSkeleton 클래스를위한 새로운 nHiberante 세션을 만들어야한다고 생각했습니다. 코드는 다음과 같습니다 :
public class Custom : AppenderSkeleton
{
protected override void Append(LoggingEvent loggingEvent)
{
if (loggingEvent != null)
{
using (ISession session = NHibernateHelper.OpenSession())
{
using (ITransaction tran = session.BeginTransaction())
{
Log data = new Log
{
Date = loggingEvent.TimeStamp,
Level = loggingEvent.Level.ToString(),
Logger = loggingEvent.LoggerName,
Thread = loggingEvent.ThreadName,
Message = loggingEvent.MessageObject.ToString()
};
if (loggingEvent.ExceptionObject != null)
{
data.Exception = loggingEvent.ExceptionObject.ToString();
}
session.Save(data);
tran.Commit();
}
}
}
}
간단한 충분히 생각 정말, 지금의 기본 형태에있는 동안, 나는 정보 등을 확인 이상의 오류가하지만 지금은 문제가이 완벽하게 작동하면서 여러 세션을 생성하는 것입니다. 즉, GetCurrentSession을 사용할 수 없기 때문에 기록 된 오류 당 새 세션을 만듭니다.이 세션은 호출 세션 (기본 프로그램 흐름)을 가져올 것이기 때문입니다. Log4Net의 스레드를 위해 전체적으로 세션을 생성 할 수있는 방법이 있지만 확실하지 않습니다. 이미 Global.asax에의 아래 사용 intial 쓰레드에 세션을 바인딩 염두에두고 (Application_BeginRequest) :
ISession session = NHibernateHelper.OpenSession();
CurrentSessionContext.Bind(session);
그리고 물을 것이다 그 사람들을 위해
, 내 도우미의 내용은 다음과 같습니다 (이은에 DLL) :public static class NHibernateHelper
{
private static Configuration _nHibernateConfig;
private static ISessionFactory _nHibernateSessionFactory;
private static ISessionFactory BuildNHibernateSessionFactory
{
get
{
if (_nHibernateSessionFactory == null)
{
if (_nHibernateConfig == null)
{
BuildSessionFactory();
}
_nHibernateSessionFactory = _nHibernateConfig.BuildSessionFactory();
}
return _nHibernateSessionFactory;
}
}
private static Configuration BuildNHibernateConfig
{
get
{
if (_nHibernateConfig == null)
{
_nHibernateConfig = new ConfigurationBuilder().Build();
}
return _nHibernateConfig;
}
}
public static Configuration nHibernateConfig
{
get
{
return _nHibernateConfig;
}
}
public static ISessionFactory nHibernateSessionFactory
{
get
{
return _nHibernateSessionFactory;
}
}
public static Configuration BuildConfiguration()
{
return BuildNHibernateConfig;
}
public static ISessionFactory BuildSessionFactory()
{
return BuildNHibernateSessionFactory;
}
public static ISession OpenSession()
{
return _nHibernateSessionFactory.OpenSession();
}
public static ISession GetCurrentSession()
{
try
{
return _nHibernateSessionFactory.GetCurrentSession();
}
catch (HibernateException ex)
{
if(ex.Message == "No session bound to the current context")
{
// See if we can bind a session before complete failure
return _nHibernateSessionFactory.OpenSession();
}
else
{
throw;
}
}
catch (Exception ex)
{
throw;
}
}
}
은 내가 log4net에서 ADO의 펜더를 사용할 수 있습니다 실현하지만 데이터베이스에 데이터를 추가하기 위해 직접 nHibernate 수를 사용하고 싶습니다. 그 이유는 nHibernate가 이미 작동하고있을 때 connectionstrings 등으로 엉망이되고 싶지 않기 때문이다.
항상 그렇듯이 모든 도움은 언제나 감사하겠습니다.
- 편집 : - 나는 initialy 말되었다 무엇을, 나는 내 사용자 지정 Log4Net 로거 코드 수정에
는 그래서 기초. 아래 두 가지 버전이 있습니다. 제 질문이 가장 좋으며 더 좋은 방법이 있습니까?
첫째, nHibernate 수 교수에 따르면, 단지 두 개의 세션을 생성 - intial 세션 의도 메인 프로그램 흐름 내 Log4Net 로거 부호의 초이다. 그러나 이것은 두 번째 세션에서 수백 명의 엔터 리를 가지며 너무 많은 엔터 리와 데이터베이스에 대한 많은 호출에 대해 불평합니다.
두 번째 nHibernate 교수는 메인 프로그램 흐름에 대한 로거 +1 호출만큼 많은 세션을 보여줍니다. 그러나 nHprof 어디서나 불만은 없습니다. 나는 많은 세션을 갖는 것이 사람들을 찌르는 듯이 보이게하거나 너무 많은 임무를 수행한다는 느낌을 갖지만.
어쨌든
코드 :
코드 1 -
protected override void Append(LoggingEvent loggingEvent)
{
if (!System.Web.HttpContext.Current.Items.Contains("Log4Net nHibernate Session"))
{
System.Web.HttpContext.Current.Items.Add("Log4Net nHibernate Session", NHibernateHelper.OpenStatelessSession());
}
IStatelessSession statelessSession = System.Web.HttpContext.Current.Items["Log4Net nHibernate Session"] as IStatelessSession;
if (statelessSession != null && loggingEvent != null)
{
using (ITransaction tran = statelessSession.BeginTransaction())
{
Log data = new Log
{
Id = Guid.NewGuid(),
Date = loggingEvent.TimeStamp,
Level = loggingEvent.Level.ToString(),
Logger = loggingEvent.LoggerName,
Thread = loggingEvent.ThreadName,
Message = loggingEvent.MessageObject.ToString()
};
if (loggingEvent.ExceptionObject != null)
{
data.Exception = loggingEvent.ExceptionObject.ToString();
}
statelessSession.Insert(data);
tran.Commit();
}
}
}
코드 2 -
protected override void Append(LoggingEvent loggingEvent)
{
if (loggingEvent != null)
{
using (IStatelessSession statelessSession = NHibernateHelper.OpenStatelessSession())
using (ITransaction tran = statelessSession.BeginTransaction())
{
Log data = new Log
{
Id = Guid.NewGuid(),
Date = loggingEvent.TimeStamp,
Level = loggingEvent.Level.ToString(),
Logger = loggingEvent.LoggerName,
Thread = loggingEvent.ThreadName,
Message = loggingEvent.MessageObject.ToString()
};
if (loggingEvent.ExceptionObject != null)
{
data.Exception = loggingEvent.ExceptionObject.ToString();
}
statelessSession.Insert(data);
tran.Commit();
}
}
}
NHibernate를 사용하여 NHibernate 디버그 메시지를 기록하면 무한 루프가되어 컴퓨터가 녹지 않을까요? – dotjoe
그런 다음 중복 또는 재실행을 확인해야합니다. 어쨌든, 지금까지, 내 애플 리케이션의 시작, 그냥 기본적인 것은, 약 300 디버그 메시지를 nHibernate 및 루프에서 로그 : – Anthony
StatelessSession 갈 방법입니다. 당신은 그것에 어떤 문제도 가지지 않을 것입니다. –