FluentNHibernate 매핑 구성을 테스트하는 통합 테스트를 작성하려고합니다. 테스트의 기본 개념은 일부 데이터를 삽입 한 다음 다시 읽고 삽입 된 데이터가 다시 읽은 데이터와 일치하는지 확인하는 것입니다. 모든 테스트 실행에서 데이터베이스에 테스트 데이터를 추가하고 싶지 않으므로 트랜잭션을 사용하여 데이터를 삽입하려고 시도하고 해당 트랜잭션이 아직 열려있는 동안 커밋되지 않은 데이터를 다시 읽으려고합니다 (별도 세션 사용). . 계획은 일단 어설 션이 작성되면 데이터 삽입과 관련하여 트랜잭션을 롤백하여 테스트가 실행되기 전과 동일한 상태로 데이터베이스를 유지하는 것입니다. 불행히도 데이터를 읽으려고 할 때 다음 오류가 발생합니다.
NHibernate.Exceptions.GenericADOException : could not load an entity: [CQRSTutorial.DAL.EventDescriptor#51ff4d15-ddbc-4157-8652-a7a10177a6e3][SQL: SELECT eventdescr0_.Id as Id1_2_0_, eventdescr0_.EventType as EventT2_2_0_, eventdescr0_.Data as Data3_2_0_ FROM Events eventdescr0_ WHERE eventdescr0_.Id=?] ----> System.Data.SqlClient.SqlException : Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
이 문제를 강조하기 위해 다음과 같이 특별히 테스트를 만들었습니다.
[TestFixture, Category(TestConstants.Integration)]
public class TimeoutExpiredTest
{
private ISession _writeSession;
public static ISessionFactory CreateSessionFactory(IsolationLevel isolationLevel = IsolationLevel.Unspecified)
{
var msSqlConfiguration = MsSqlConfiguration
.MsSql2012
.IsolationLevel(isolationLevel)
.ConnectionString(x => x.FromConnectionStringWithKey("CQRSTutorial"));
var cfg = new CustomAutomappingConfiguration();
return Fluently
.Configure()
.Database(msSqlConfiguration)
.Mappings(m =>
{
m.AutoMappings.Add(
AutoMap.AssemblyOf<EventDescriptor>(cfg)
.UseOverridesFromAssemblyOf<EventDescriptorMapping>());
})
.BuildSessionFactory();
}
[SetUp]
public void SetUp()
{
_writeSession = CreateSessionFactory().OpenSession();
_writeSession.BeginTransaction();
}
[Test]
public void InsertAndReadTabOpened()
{
var objectToStoreInDbTemporarily = GetObjectToStoreInDbTemporarily();
_writeSession.SaveOrUpdate(objectToStoreInDbTemporarily);
_writeSession.Flush(); // the data needs to go to the database (even if only temporarily), rather than just staying in an NHibernate cache.
var readSession = CreateSessionFactory(IsolationLevel.ReadUncommitted).OpenSession();
var retrievedEventDescriptor = readSession.Get<EventDescriptor>(objectToStoreInDbTemporarily.Id); // this line throws the exception after 30 seconds.
// If previous line worked, I could then assert inserted values match retrieved values at this point.
}
[TearDown]
public void TearDown()
{
_writeSession.Transaction?.Rollback();
}
public class CustomAutomappingConfiguration : DefaultAutomappingConfiguration
{
public override bool ShouldMap(Type type)
{
return type.Name == typeof(EventDescriptor).Name; // we're only mapping this class for now.
}
}
간결함을 위해 객체를 생성하는 코드는 생략했습니다. 원래 테스트는 그 목적을 달성했습니다. 문제의 개체에 대한 NHibernate 매핑을 올바르게 정의해야했습니다. 그러나 원래 테스트는 모든 테스트 실행에 새 행을 삽입하는 것이 었는데, 이는 더럽고 불필요하다고 느껴집니다. 따라서이 트랜잭션 / 롤백 접근 방식입니다.
SQL 프로필러를 살펴보면 문제가 읽기쪽에있는 것 같습니다. 읽기 세션이 IsolationLevel.ReadUncommitted가 아닌 IsolationLevel.ReadCommitted를 사용하고 있습니다. 읽기 세션이 테스트에 지정된 IsolationLevel을 사용하지 않는 이유는 무엇입니까?
아, 방금 다시 살펴 봤는데 그게 readSession.Get()
명시적인 거래가 없기 때문인지 궁금 합니다. 따라서 NH는 읽기 커밋 된 격리 수준으로 암시 적 트랜잭션을 사용하고 있습니까? readSession.Get()
커밋되지 않은 읽기 격리 수준으로 명시 적 트랜잭션으로 래핑 할 수 있습니까?
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다