2

Ich verwende In-Memory-Datenbank (mit ServiceStack.Ormlite.Sqlite.Windows) für Komponententests in Servicestack-basierten Web-API. Ich mag die Service-Endpunkte testen, die auf gespeicherte Prozeduren durch In-Memory-Datenbank ab, für den ich über den Link gegangen Servicestack Ormlite SqlServerProviderTests, die Unit-Test-Klasse, die ich für den Test verwende wird wie folgt,Hinzufügen gespeicherter Prozeduren zu In-Memory-DB mit SqLite

 using System; 
     using System.Collections.Generic; 
     using System.Data; 
     using System.Linq; 
     using NUnit.Framework; 
     using ServiceStack.Text; 
     using ServiceStack.Configuration; 
     using ServiceStack.Data; 

     namespace ServiceStack.OrmLite.Tests 
     { 
      public class DummyTable 
      { 
       public int Id { get; set; } 
       public string Name { get; set; } 
      } 

      [TestFixture] 
      public class SqlServerProviderTests 
      { 
       private IDbConnection db; 
       protected readonly ServiceStackHost appHost; 

       public SqlServerProviderTests() 
       { 
        appHost = TestHelper.SetUp(appHost).Init(); 
        db = appHost.Container.Resolve<IDbConnectionFactory>().OpenDbConnection("inventoryDb"); 

        if (bool.Parse(System.Configuration.ConfigurationManager.AppSettings["IsMock"])) 
         TestHelper.CreateInMemoryDB(appHost); 
       } 

       [TestFixtureTearDown] 
       public void TearDown() 
       { 
        db.Dispose(); 
       }  

       [Test] 
       public void Can_SqlColumn_StoredProc_returning_Column() 
       { 
        var sql = @"CREATE PROCEDURE dbo.DummyColumn 
           @Times integer 
           AS 
           BEGIN 
           SET NOCOUNT ON; 

           CREATE TABLE #Temp 
           (
           Id integer NOT NULL, 
           ); 

          declare @i int 
          set @i=1 
          WHILE @i < @Times 
          BEGIN 
          INSERT INTO #Temp (Id) VALUES (@i) 
          SET @i = @i + 1 
          END 
          SELECT * FROM #Temp; 

          DROP TABLE #Temp; 
          END;"; 
        db.ExecuteSql("IF OBJECT_ID('DummyColumn') IS NOT NULL DROP PROC DummyColumn"); 
        db.ExecuteSql(sql); 

        var expected = 0; 
        10.Times(i => expected += i); 

        var results = db.SqlColumn<int>("EXEC DummyColumn @Times", new { Times = 10 }); 
        results.PrintDump(); 
        Assert.That(results.Sum(), Is.EqualTo(expected)); 

        results = db.SqlColumn<int>("EXEC DummyColumn 10"); 
        Assert.That(results.Sum(), Is.EqualTo(expected)); 

        results = db.SqlColumn<int>("EXEC DummyColumn @Times", new Dictionary<string, object> { { "Times", 10 } }); 
        Assert.That(results.Sum(), Is.EqualTo(expected)); 
       } 
      } 
     } 

wenn Ich habe versucht, dies über Live-DB auszuführen, es funktionierte gut. aber wenn ich für In-Memory DB versucht wurde immer Ausnahmen wie folgt

 System.Data.SQLite.SQLiteException : SQL logic error or missing database near "IF": syntax error 

in der Nähe der Codezeile,

 db.ExecuteSql("IF OBJECT_ID('DummyColumn') IS NOT NULL DROP PROC DummyColumn"); 

i kommentierten die obige Zeile und den Testfall ausgeführt, aber ich bin immer noch Ausnahme bekommen wie folgt,

 System.Data.SQLite.SQLiteException : SQL logic error or missing database near "IF": syntax error 

für die Codezeile,

 db.ExecuteSql(sql); 

der In-Memory-DB erstellt wird, wie folgt, und es funktioniert gut für die übrigen Fälle.

 public static void CreateInMemoryDB(ServiceStackHost appHost) 
       { 
        using (var db = appHost.Container.Resolve<IDbConnectionFactory>().OpenDbConnection("ConnectionString")) 
        {        
         db.DropAndCreateTable<DummyData>(); 
         TestDataReader<TableList>("Reservation.json", "InMemoryInput").Reservation.ForEach(x => db.Insert(x)); 

         db.DropAndCreateTable<DummyTable>(); 

        }    
       } 

warum wir vor dieser Ausnahme gibt es eine andere Art und Weise gespeicherte Prozedur in In-Memory-DB mit SQLite hinzuzufügen und zu laufen ??

Antwort

3

Der Fehler liegt daran, dass Sie versuchen, SQL Server-spezifische Abfragen mit TSQL gegen eine Version im Speicher von Sqlite - d. H. Eine komplett andere, einbettbare Datenbank - auszuführen. Wie der Name schon sagt SqlServerProviderTests funktioniert nur auf SQL Server, ich bin verwirrt, warum Sie versuchen würden, dies gegen Sqlite auszuführen?

SQLite unterstützt keine Stored Procedures, TSQL usw. Daher führt der Versuch, SQL Server TSQL-Anweisungen auszuführen, immer zu einem Fehler. Das einzige, was Sie tun können, ist, es mit einem custom Exec Filter zu fälschen, wo Sie die Ausnahme abfangen und jedes benutzerdefinierte Ergebnis zurückgeben können, das Sie mögen, z. B .:

public class MockStoredProcExecFilter : OrmLiteExecFilter 
{ 
    public override T Exec<T>(IDbConnection dbConn, Func<IDbCommand, T> filter) 
    { 
     try 
     { 
      return base.Exec(dbConn, filter); 
     } 
     catch (Exception ex) 
     { 
      if (dbConn.GetLastSql() == "exec sp_name @firstName, @age") 
       return (T)(object)new Person { FirstName = "Mocked" }; 
      throw; 
     } 
    } 
} 

OrmLiteConfig.ExecFilter = new MockStoredProcExecFilter();