我已将我的全部包裹SQL Connections在一个using声明中。
using (DbConnection dbConnection = GetConnection())\n{\n using (DbCommand dbCommand = dbConnection.CreateCommand(cmdInsert))\n {\n //some work\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n因为UnitTests我应该使用 a :memory: database,但是database关闭连接后会自动删除。
https://www.sqlite.org/inmemorydb.html
\n\n\n\n\n当与数据库的最后一个连接关闭时,数据库将被自动删除并回收内存。
\n
有没有解决方案如何使用 a:memory: database和 use using?我不想在没有..的情况下编写完全相同的代码两次using。
public abstract class SqliteBase\n{\n public string ConnectionString;\n\n protected SqliteBase()\n { \n SQLiteConnectionStringBuilder builder = new SQLiteConnectionStringBuilder\n {\n DataSource = ":memory:",\n ForeignKeys = true,\n DefaultTimeout = 3,\n DateTimeKind = DateTimeKind.Utc,\n Pooling = false \n };\n\n ConnectionString = builder.ConnectionString + ";mode=memory;cache=shared";\n }\n\n private DbConnection _MemoryConnection;\n protected DbConnection GetConnection()\n {\n try\n {\n if (_MemoryConnection == null)\n {\n _MemoryConnection = new SQLiteConnection(ConnectionString); \n _MemoryConnection.Open();\n }\n\n DbConnection dbConnection = new SQLiteConnection(ConnectionString);\n dbConnection.Open();\n\n return dbConnection;\n }\n\n catch (Exception ex)\n {\n throw new Exception("Error opening database connection.", ex);\n }\n }\n\n /// <summary>\n /// Creates a table in the SQL database if it does not exist\n /// </summary>\n /// <param name="tableName">The name of the table</param>\n /// <param name="columns">Comma separated column names</param>\n protected void CreateTable(string tableName, string columns)\n {\n using (DbConnection dbConnection = GetConnection())\n {\n using (DbCommand dbCommand = dbConnection.CreateCommand($"create table if not exists {tableName} ({columns})"))\n {\n dbCommand.ExecuteNonQuery();\n }\n }\n }\n}\n\npublic class FooDatabase : SqliteBase\n{\n public FooDatabase()\n {\n CreateTable("FooTable", "Foo TEXT");\n }\n\n public void DoFoo()\n {\n using (DbConnection dbConnection = GetConnection())\n {\n using (DbCommand dbCommand = dbConnection.CreateCommand("Select * from FooTable"))\n {\n dbCommand.ExecuteNonQuery();\n }\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\npublic static class SQLiteTestSetup\n{\n public static FooDatabase ClassInit()\n {\n return new FooDatabase();\n }\n\n public static void Cleanup()\n {\n\n }\n}\n\npublic abstract class SQLiteTestBase\n{\n public static FooDatabase Database { get; set; }\n\n [TestMethod]\n public void DoSomeFooTest()\n {\n Database.DoFoo();\n }\n}\n\n[TestClass]\npublic class SQLiteTest : SQLiteTestBase\n{\n [ClassInitialize]\n public static void ClassInit(TestContext context)\n {\n Database = SQLiteTestSetup.ClassInit();\n }\n\n [ClassCleanup]\n public static void ClassCleanup() => SQLiteTestSetup.Cleanup();\n}\nRun Code Online (Sandbox Code Playgroud)\n\nDie Testmethode "....SQLiteTest.DoSomeFooTest" hat eine Ausnahme ausgel\xc3\xb6st: \nSystem.Data.SQLite.SQLiteException: SQL logic error\nno such table: FooTable\n bei System.Data.SQLite.SQLite3.Prepare(SQLiteConnection cnn, String strSql, SQLiteStatement previous, UInt32 timeoutMS, String& strRemain)\n bei System.Data.SQLite.SQLiteCommand.BuildNextCommand()\n bei System.Data.SQLite.SQLiteCommand.GetStatement(Int32 index)\n bei System.Data.SQLite.SQLiteDataReader.NextResult()\n bei System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavior behave)\n bei System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior)\n bei System.Data.SQLite.SQLiteCommand.ExecuteNonQuery(CommandBehavior behavior)\n bei System.Data.SQLite.SQLiteCommand.ExecuteNonQuery()\n bei ....FooDatabase.DoFoo() in ...\\SqliteDatabaseBase.cs:Zeile 83.\n bei ....SQLiteTestBase.DoSomeFooTest() in ...\\SQLiteTest.cs:Zeile 30.\nRun Code Online (Sandbox Code Playgroud)\n
我添加了一个ConnectionContext类,我可以在其中设置一个标志来决定是否要处置我的DbConnection。
public class ConnectionContext : IDisposable
{
private readonly bool _ContextOwnsConnection;
public readonly DbConnection Connection;
public ConnectionContext(DbConnection connection, bool contextOwnsConnection)
{
Connection = connection;
_ContextOwnsConnection = contextOwnsConnection;
}
public void Dispose()
{
if(_ContextOwnsConnection)
Connection.Dispose();
}
}
public abstract class SqliteBase
{
public Func<ConnectionContext> GetContext;
private ConnectionContext _GetConnectionContext()
{
return new ConnectionContext(GetConnection(), true);
}
private string _ConnectionString;
private readonly string _Dbfile;
protected SqliteBase()
{
GetContext = _GetConnectionContext;
_Dbfile = ":memory:";
_InitConnectionString();
}
private void _InitConnectionString()
{
SQLiteConnectionStringBuilder builder = new SQLiteConnectionStringBuilder
{
DataSource = _Dbfile,
ForeignKeys = true,
DefaultTimeout = 3,
DateTimeKind = DateTimeKind.Utc,
Pooling = true
};
_ConnectionString = builder.ConnectionString;
}
public DbConnection GetConnection()
{
try
{
DbConnection dbConnection = SQLiteFactory.Instance.CreateConnection();
dbConnection.ConnectionString = _ConnectionString;
dbConnection.Open();
return dbConnection;
}
catch (Exception ex)
{
throw new Exception("Error opening database connection.", ex);
}
}
/// <summary>
/// Creates a table in the SQL database if it does not exist
/// </summary>
/// <param name="tableName">The name of the table</param>
/// <param name="columns">Comma separated column names</param>
protected void CreateTable(string tableName, string columns)
{
using (ConnectionContext context = GetContext())
{
using (DbCommand dbCommand = context.Connection.CreateCommand($"create table if not exists {tableName} ({columns})"))
{
dbCommand.ExecuteNonQuery();
}
}
}
}
public class FooDatabase : SqliteBase
{
public FooDatabase()
{
Initialize();
}
public void Initialize()
{
CreateTable("FooTable", "Foo TEXT");
}
public void DoFoo()
{
using (ConnectionContext context = GetContext())
{
using (DbCommand dbCommand = context.Connection.CreateCommand("Select * from FooTable"))
{
dbCommand.ExecuteNonQuery();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
public abstract class SQLiteTestBase
{
public static ConnectionContext Connection { get; set; }
public static FooDatabase Database { get; set; }
[TestMethod]
public void DoSomeFooTest()
{
Database.DoFoo();
}
}
[TestClass]
public class SQLiteTest : SQLiteTestBase
{
[ClassInitialize]
public static void ClassInit(TestContext context)
{
Database = new FooDatabase();
Database.GetContext = () => Connection;
Connection = new ConnectionContext(Database.GetConnection(), false);
}
[TestInitialize]
public void TestInit()
{
Connection = new ConnectionContext(Database.GetConnection(), false);
Database.Initialize();
}
[TestCleanup]
public void TestCleanup()
{
Connection.Dispose();
Connection = null;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5573 次 |
| 最近记录: |