문제

나는 DataAnsess에 nhibernate를 사용하고 잠시 동안 로컬 통합 테스트에 SQLITE를 사용하지 않았습니다. 파일을 사용하고 있었지만 다음을 수행 할 것이라고 생각했습니다. 메모리 : 옵션. 통합 테스트를 시작하면 데이터베이스가 생성 된 것으로 보이지만 (Nhibernate는 테이블 생성 SQL을 뱉어냅니다) 데이터베이스와 intercaction은 오류가 발생합니다.

Memory Database와 함께 일하는 사람이있는 사람이 있습니까? 가능합니까? 내가 사용하는 연결 문자열은 다음과 같습니다.

Data Source=:memory:;Version=3;New=True
도움이 되었습니까?

해결책

SQLITE 메모리 데이터베이스는 연결이 열려있는 한만 존재합니다. nhibernate와 함께 단위 테스트에서 사용하려면 :
1. 테스트 시작시 ISESSION을 열십시오 (아마도 [설정] 방법으로).
2. SchemaExport 호출에서 해당 세션의 연결을 사용하십시오.
3. 테스트에서 동일한 세션을 사용하십시오.
4. 테스트 종료시 세션을 닫습니다 (아마도 [Teardown] 방법으로).

다른 팁

SQLITE 인 메모리 데이터베이스를 사용할 수 있었고 SQLITE 's를 사용하여 각 테스트에 대한 스키마를 재건 할 필요가 없었습니다. '공유 캐시'지원, 이를 통해 메모리 내 데이터베이스를 연결 전체에서 공유 할 수 있습니다.

나는 다음을했다 조립 기관 (나는 mstest를 사용하고 있습니다) :

  • 다음 연결 문자열과 함께 sqlite를 사용하도록 nhibernate (flually)를 구성하십시오.

    FullUri=file:memorydb.db?mode=memory&cache=shared
    
  • 해당 구성을 사용하여 HBM2DDL을 만듭니다.SchemaExport 개체하고 별도의 연결에서 실행하십시오 (그러나 동일한 연결 문자열로 다시).

  • 그 연결을 열어두고 정적 필드가 참조하십시오. 조립 청소, 그 시점에서 그것은 폐쇄되어 폐기됩니다. 이는 SQLITE가 메모리 내 데이터베이스에서 적어도 하나의 활성 연결이 필요하기 때문에 여전히 필요하다는 것을 알기 위해서는 정리를 피하고 정리하지 않기 때문입니다.

각 테스트가 실행되기 전에 새로운 세션이 만들어지고 테스트는 끝에 롤백되는 트랜잭션에서 실행됩니다.

다음은 테스트 어셈블리 수준 코드의 예입니다.

[TestClass]
public static class SampleAssemblySetup
{
    private const string ConnectionString = "FullUri=file:memorydb.db?mode=memory&cache=shared";
    private static SQLiteConnection _connection;

    [AssemblyInitialize]
    public static void AssemblyInit(TestContext context)
    {
        var configuration = Fluently.Configure()
                                       .Database(SQLiteConfiguration.Standard.ConnectionString(ConnectionString))
                                       .Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.Load("MyMappingsAssembly")))
                                       .ExposeConfiguration(x => x.SetProperty("current_session_context_class", "call"))
                                       .BuildConfiguration();

        // Create the schema in the database
        // Because it's an in-memory database, we hold this connection open until all the tests are finished
        var schemaExport = new SchemaExport(configuration);
        _connection = new SQLiteConnection(ConnectionString);
        _connection.Open();
        schemaExport.Execute(false, true, false, _connection, null);
    }

    [AssemblyCleanup]
    public static void AssemblyTearDown()
    {
        if (_connection != null)
        {
            _connection.Dispose();
            _connection = null;
        }
    }
}

각 단위 테스트 클래스/고정물에 대한 기본 클래스 :

public class TestBase
{
    [TestInitialize]
    public virtual void Initialize()
    {
        NHibernateBootstrapper.InitializeSession();
        var transaction = SessionFactory.Current.GetCurrentSession().BeginTransaction();
    }

    [TestCleanup]
    public virtual void Cleanup()
    {
        var currentSession = SessionFactory.Current.GetCurrentSession();
        if (currentSession.Transaction != null)
        {
            currentSession.Transaction.Rollback();
            currentSession.Close();
        }

        NHibernateBootstrapper.CleanupSession();
    }
}

자원 관리가 개선 될 수 있지만 인정하지만 결국 단위 테스트입니다 (제안 된 개선을 환영합니다!).

우리는 모든 데이터베이스 테스트에 메모리에 SQLITE를 사용하고 있습니다. 우리는 동일한 테스트로 열린 모든 NH 세션에 대해 재사용되는 테스트에 단일 ADO 연결을 사용하고 있습니다.

  1. 모든 테스트 전에 : 연결을 만듭니다
  2. 이 연결에서 스키마를 만듭니다
  3. 실행 테스트. 모든 세션에 동일한 연결이 사용됩니다
  4. 테스트 후 : 연결을 닫습니다

이를 통해 여러 세션이 포함 된 테스트를 실행할 수 있습니다. 매핑 파일을 읽는 데 꽤 시간이 걸리기 때문에 SessionFactory는 모든 테스트에 대해 한 번 생성됩니다.


편집하다

공유 캐시 사용

System.data.sqlite 1.0.82 이후 (또는 SQLITE 3.7.13), 이있다 공유 캐시, 몇 가지 연결이 동일한 데이터를 공유 할 수 있으며 메모리 내 데이터베이스. 이를 통해 메모리-다타베이스를 한 번 연결하고 다른 연결에서 사용할 수 있습니다. (아직 시도하지는 않았지만 이론적으로는 효과가 있어야합니다) :

  • 연결 문자열을 변경하십시오 file::memory:?cache=shared
  • 연결을 열고 스키마를 만듭니다
  • 테스트가 끝날 때 까지이 연결을 열어 두십시오.
  • NH가 테스트 중에 다른 연결 (정상 동작)을 생성하도록하십시오.

위에서 언급 한 바와 같이 ISESSION을 열고 나서도 "풀링 = true; 최대 풀 크기 = 1"을 연결 문자열에 추가하는 비슷한 문제가있었습니다. 도움이되었지만 테스트 중에 연결이 닫히는 경우가 여전히 남아있었습니다 (일반적으로 거래를 저지른 직후).

마지막으로 저를 위해 일한 것은 내 SessionFactory 구성에서 속성 "Connection.Release_Mode"를 "on_close"로 설정하는 것이 었습니다.

app.config 파일의 내 구성은 이제 이것을 좋아합니다.

  <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    <reflection-optimizer use="true" />
    <session-factory>
      <property name="connection.connection_string_name">testSqlLiteDB</property>
      <property name="connection.driver_class">NHibernate.Driver.SQLite20Driver</property>
      <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
      <property name="connection.release_mode">on_close</property>
      <property name="dialect">NHibernate.Dialect.SQLiteDialect</property>
      <property name="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>
      <property name="query.substitutions">true=1;false=0</property>
    </session-factory>
  </hibernate-configuration>

도움이되기를 바랍니다!

단지 거친 추측이지만 SQL은 SQLITE가 지원하지 않은 명령을 사용하여 nhibernate에 의한 SQL 출력입니까?

또한 메모리 대신 파일을 사용하면 어떻게됩니까? (system.io.path.getTempFilename ()가 작동 할 것 같아요 ...)

나는 그것을하고있다 코뿔소 커먼즈. Rhino Commons를 사용하고 싶지 않다면 소스를 연구 할 수 있습니다. 내가 가진 유일한 문제는 SQLITE가 중첩 거래를 지원하지 않는다는 것입니다. 이로 인해 통합 테스트를 지원하기 위해 코드를 변경해야했습니다. In Memory 데이터베이스와의 통합 테스트는 매우 훌륭합니다. 나는 그것이 공정한 타협이라고 결정했습니다.

SQLITE 메모리 데이터베이스의 문제가 많이 없습니다. 이제 우리는 Ramdrive 디스크에서 파일로 작업하는 sqlite를 사용하고 있습니다.

Decates에게 감사하고 싶습니다. 몇 달 동안 이것을 해결하려고 노력했고 내가해야 할 일은 추가뿐만 아니라

FullUri=file:memorydb.db?mode=memory&cache=shared

nhibernate config 파일의 연결 문자열로 또한 *.hbm.xml과 함께 nhibernate 만 사용하고 fnh가 아니라 실제로 내 코드를 전혀 수정할 필요가 없었습니다!

SQLITE NUGET 패키지를 가져 오는 것을 잊었을 때도 같은 오류가 발생했습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top