Просмотр исходного кода

[Vitorm] new feature to change mapped table and change database for sharding

Lith 10 месяцев назад
Родитель
Сommit
6815263a63

+ 17 - 0
README.md

@@ -32,6 +32,23 @@ This means you get the best of both worlds: the performance and simplicity of Da
 # Vitorm Documentation
 This guide will walk you through the steps to set up and use Vitorm with SQLite.
 
+supported features:
+
+| feature    |  method   |  remarks   |     |
+| --- | --- | --- | --- |
+|  create table   |  Create   |     |     |
+|  drop table   |  Drop   |     |     |
+| --- | --- | --- | --- |
+|  create records   |  Add AddRange   |     |     |
+|  retrieve  records |  Query Get   |     |     |
+|  update records   |  Update UpdateRange ExecuteUpdate  |     |     |
+|  delete records   |  Delete DeleteRange DeleteByKey DeleteByKeys ExecuteDelete   |     |     |
+| --- | --- | --- | --- |
+|  change table   |  ChangeTable    |  change mapping table from database   |   |
+|  change database  |  ChangeDatabase   | change database to be connected  |   |
+|     |     |   |   |
+
+
 ## Installation
 Before using Vitorm, install the necessary package:
 

+ 1 - 0
doc/ReleaseLog.md

@@ -12,6 +12,7 @@
 - [Vitorm.SqlServer] fix bool type was not supported in database issue (especially in select sentence)
 - [Vitorm.ClickHouse] fix String.Add null value and cast issue : ifNull(  cast( (userFatherId) as Nullable(String) ) , ''  )
 - [Vitorm.Sqlite] fix String.Add null value and cast issue
+- [Vitorm] new feature to change mapped table and change database for sharding
 
 -----------------------
 # 1.1.0

+ 3 - 0
doc/TODO.md

@@ -1,6 +1,9 @@
 # Vitorm TODO
 
 
+rename Create to TryCreateTable
+rename Drop to TryDropTable
+
 
 # group then orderBy aggregate column
 > [QueryTranslator] not suported MethodCall: Sum

+ 20 - 6
src/Vitorm.MySql/DbConfig.cs

@@ -1,7 +1,9 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
 using System.Data;
 
+using Vitorm.Sql;
+
+using ConnectionStringBuilder = MySqlConnector.MySqlConnectionStringBuilder;
 using DbConnection = MySqlConnector.MySqlConnection;
 
 namespace Vitorm.MySql
@@ -36,11 +38,23 @@ namespace Vitorm.MySql
         public string readOnlyConnectionString { get; set; }
         public int? commandTimeout { get; set; }
 
-        internal string dbHashCode => connectionString.GetHashCode().ToString();
-        internal IDbConnection createDbConnection() => new DbConnection(connectionString);
-        private IDbConnection _createReadOnlyDbConnection() => new DbConnection(readOnlyConnectionString);
 
-        internal Func<IDbConnection> createReadOnlyDbConnection => readOnlyConnectionString == null ? null : _createReadOnlyDbConnection;
+        public static string ChangeDatabaseForConnecitonString(string connectionString, string databaseName)
+            => new ConnectionStringBuilder(connectionString) { Database = databaseName }.ConnectionString;
+
+        public static string GetDatabaseName(string connectionString) => new ConnectionStringBuilder(connectionString).Database;
+
+        public static IDbConnection CreateDbConnection(string connectionString) => new DbConnection(connectionString);
+
+
+        public DbConnectionProvider ToDbConnectionProvider()
+            => new DbConnectionProvider(
+                createDbConnection: CreateDbConnection,
+                changeDatabaseForConnectionString: ChangeDatabaseForConnecitonString,
+                getDatabaseName: GetDatabaseName,
+                connectionString: connectionString,
+                readOnlyConnectionString: readOnlyConnectionString
+                );
 
     }
 }

+ 1 - 3
src/Vitorm.MySql/DbContext_Extensions_UseMySql.cs

@@ -13,9 +13,7 @@ namespace Vitorm
         {
             dbContext.Init(
                 sqlTranslateService: Vitorm.MySql.SqlTranslateService.Instance,
-                createDbConnection: config.createDbConnection,
-                createReadOnlyDbConnection: config.createReadOnlyDbConnection,
-                    dbHashCode: config.dbHashCode
+                dbConnectionProvider: config.ToDbConnectionProvider()
                 );
 
             dbContext.createTransactionScope = createTransactionScope;

+ 19 - 4
src/Vitorm.SqlServer/DbConfig.cs

@@ -2,7 +2,10 @@
 using System.Collections.Generic;
 using System.Data;
 
+using Vitorm.Sql;
+
 using DbConnection = Microsoft.Data.SqlClient.SqlConnection;
+using ConnectionStringBuilder = Microsoft.Data.SqlClient.SqlConnectionStringBuilder;
 
 namespace Vitorm.SqlServer
 {
@@ -36,11 +39,23 @@ namespace Vitorm.SqlServer
         public string readOnlyConnectionString { get; set; }
         public int? commandTimeout { get; set; }
 
-        internal string dbHashCode => connectionString.GetHashCode().ToString();
-        internal IDbConnection createDbConnection() => new DbConnection(connectionString);
-        private IDbConnection _createReadOnlyDbConnection() => new DbConnection(readOnlyConnectionString);
 
-        internal Func<IDbConnection> createReadOnlyDbConnection => readOnlyConnectionString == null ? null : _createReadOnlyDbConnection;
+        public static string ChangeDatabaseForConnecitonString(string connectionString, string databaseName)
+            => new ConnectionStringBuilder(connectionString) { InitialCatalog = databaseName }.ConnectionString;
+
+        public static string GetDatabaseName(string connectionString) => new ConnectionStringBuilder(connectionString).InitialCatalog;
+
+        public static IDbConnection CreateDbConnection(string connectionString) => new DbConnection(connectionString);
+
+
+        public DbConnectionProvider ToDbConnectionProvider()
+            => new DbConnectionProvider(
+                createDbConnection: CreateDbConnection,
+                changeDatabaseForConnectionString: ChangeDatabaseForConnecitonString,
+                getDatabaseName: GetDatabaseName,
+                connectionString: connectionString,
+                readOnlyConnectionString: readOnlyConnectionString
+                );
 
     }
 }

+ 1 - 3
src/Vitorm.SqlServer/DbContext_Extensions_UseSqlServer.cs

@@ -13,9 +13,7 @@ namespace Vitorm
         {
             dbContext.Init(
                 sqlTranslateService: Vitorm.SqlServer.SqlTranslateService.Instance,
-                createDbConnection: config.createDbConnection,
-                createReadOnlyDbConnection: config.createReadOnlyDbConnection,
-                dbHashCode: config.dbHashCode
+                dbConnectionProvider: config.ToDbConnectionProvider()
                 );
 
             dbContext.createTransactionScope = createTransactionScope;

+ 20 - 6
src/Vitorm.Sqlite/DbConfig.cs

@@ -1,7 +1,9 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
 using System.Data;
 
+using Vitorm.Sql;
+
+using ConnectionStringBuilder = Microsoft.Data.Sqlite.SqliteConnectionStringBuilder;
 using DbConnection = Microsoft.Data.Sqlite.SqliteConnection;
 
 namespace Vitorm.Sqlite
@@ -36,11 +38,23 @@ namespace Vitorm.Sqlite
         public string readOnlyConnectionString { get; set; }
         public int? commandTimeout { get; set; }
 
-        internal string dbHashCode => connectionString.GetHashCode().ToString();
-        internal IDbConnection createDbConnection() => new DbConnection(connectionString);
-        private IDbConnection _createReadOnlyDbConnection() => new DbConnection(readOnlyConnectionString);
 
-        internal Func<IDbConnection> createReadOnlyDbConnection => readOnlyConnectionString == null ? null : _createReadOnlyDbConnection;
+        public static string ChangeDatabaseForConnecitonString(string connectionString, string databaseName)
+            => new ConnectionStringBuilder(connectionString) { DataSource = databaseName }.ConnectionString;
+
+        public static string GetDatabaseName(string connectionString) => new ConnectionStringBuilder(connectionString).DataSource;
+
+        public static IDbConnection CreateDbConnection(string connectionString) => new DbConnection(connectionString);
+
+
+        public DbConnectionProvider ToDbConnectionProvider()
+            => new DbConnectionProvider(
+                createDbConnection: CreateDbConnection,
+                changeDatabaseForConnectionString: ChangeDatabaseForConnecitonString,
+                getDatabaseName: GetDatabaseName,
+                connectionString: connectionString,
+                readOnlyConnectionString: readOnlyConnectionString
+                );
 
     }
 }

+ 1 - 3
src/Vitorm.Sqlite/DbContext_Extensions_UseSqlite.cs

@@ -13,9 +13,7 @@ namespace Vitorm
         {
             dbContext.Init(
                 sqlTranslateService: Vitorm.Sqlite.SqlTranslateService.Instance,
-                createDbConnection: config.createDbConnection,
-                createReadOnlyDbConnection: config.createReadOnlyDbConnection,
-                dbHashCode: config.dbHashCode
+                dbConnectionProvider: config.ToDbConnectionProvider()
                 );
 
             dbContext.createTransactionScope = createTransactionScope;

+ 30 - 1
src/Vitorm/DbContext.cs

@@ -38,10 +38,39 @@ namespace Vitorm
         public static DefaultEntityLoader defaultEntityLoader = new();
 
         public IEntityLoader entityLoader = defaultEntityLoader;
-        public virtual IEntityDescriptor GetEntityDescriptor(Type entityType) => entityLoader.LoadDescriptor(entityType);
+        public virtual IEntityDescriptor GetEntityDescriptor(Type entityType, bool tryFromCache = true)
+        {
+            if (tryFromCache && dbSetMap?.TryGetValue(entityType, out var dbSet) == true) return dbSet.entityDescriptor;
+            return entityLoader.LoadDescriptor(entityType);
+        }
+        public virtual IEntityDescriptor GetEntityDescriptor<Entity>(bool tryFromCache = true)
+            => GetEntityDescriptor(typeof(Entity), tryFromCache);
         #endregion
 
 
+        #region ChangeTable ChangeTableBack
+
+        public virtual IDbSet ChangeTable(Type entityType, string tableName)
+        {
+            var dbSet = DbSet(entityType);
+            dbSet?.ChangeTable(tableName);
+            return dbSet;
+        }
+        public virtual DbSet<Entity> ChangeTable<Entity>(string tableName)
+            => ChangeTable(typeof(Entity), tableName) as DbSet<Entity>;
+
+
+        public virtual IDbSet ChangeTableBack(Type entityType)
+        {
+            var dbSet = DbSet(entityType);
+            dbSet?.ChangeTableBack();
+            return dbSet;
+        }
+        public virtual DbSet<Entity> ChangeTableBack<Entity>()
+            => ChangeTableBack(typeof(Entity)) as DbSet<Entity>;
+
+        #endregion
+
 
 
         #region DbSet

+ 6 - 5
src/Vitorm/DbSet.cs

@@ -7,11 +7,6 @@ using Vitorm.Entity;
 
 namespace Vitorm
 {
-    public interface IDbSet
-    {
-        IEntityDescriptor entityDescriptor { get; }
-    }
-
     public class DbSetConstructor
     {
         public static IDbSet CreateDbSet(DbContext dbContext, Type entityType, IEntityDescriptor entityDescriptor)
@@ -44,6 +39,12 @@ namespace Vitorm
             this._entityDescriptor = entityDescriptor;
         }
 
+
+        public virtual IEntityDescriptor ChangeTable(string tableName) => _entityDescriptor = _entityDescriptor.WithTable(tableName);
+        public virtual IEntityDescriptor ChangeTableBack() => _entityDescriptor = _entityDescriptor.GetOriginEntityDescriptor();
+
+
+
         public virtual void Create() => dbContext.Create<Entity>();
         public virtual void Drop() => dbContext.Drop<Entity>();
 

+ 39 - 0
src/Vitorm/Entity/DataAnnotations/EntityDescriptorWithAlias.cs

@@ -0,0 +1,39 @@
+using System;
+
+namespace Vitorm.Entity.DataAnnotations
+{
+    public partial class EntityDescriptorWithAlias : IEntityDescriptor
+    {
+        public IEntityDescriptor originEntityDescriptor { get; protected set; }
+        public EntityDescriptorWithAlias(IEntityDescriptor entityDescriptor, string tableName)
+        {
+            this.originEntityDescriptor = entityDescriptor;
+            this.tableName = tableName;
+        }
+
+
+        public Type entityType => originEntityDescriptor?.entityType;
+        public string tableName { get; protected set; }
+        public string schema => originEntityDescriptor?.schema;
+
+        /// <summary>
+        /// primary key name
+        /// </summary>
+        public string keyName => originEntityDescriptor?.keyName;
+
+        /// <summary>
+        /// primary key
+        /// </summary>
+        public IColumnDescriptor key => originEntityDescriptor?.key;
+
+        /// <summary>
+        /// not include primary key
+        /// </summary>
+        public IColumnDescriptor[] columns => originEntityDescriptor?.columns;
+
+
+        public IColumnDescriptor[] allColumns => originEntityDescriptor?.allColumns;
+
+
+    }
+}

+ 21 - 0
src/Vitorm/Extensions/IEntityDescriptor_Extensions.cs

@@ -0,0 +1,21 @@
+using Vitorm.Entity;
+using Vitorm.Entity.DataAnnotations;
+
+namespace Vitorm
+{
+    public static partial class IEntityDescriptor_Extensions
+    {
+        public static IEntityDescriptor WithTable(this IEntityDescriptor entityDescriptor, string tableName)
+            => entityDescriptor == null ? null : new EntityDescriptorWithAlias(entityDescriptor, tableName);
+
+        public static IEntityDescriptor GetOriginEntityDescriptor(this IEntityDescriptor entityDescriptor)
+        {
+            while (entityDescriptor is EntityDescriptorWithAlias entityDescriptorWithAlias)
+                entityDescriptor = entityDescriptorWithAlias.originEntityDescriptor;
+            return entityDescriptor;
+        }
+
+        public static string GetOriginTable(this IEntityDescriptor entityDescriptor) => GetOriginEntityDescriptor(entityDescriptor)?.tableName;
+
+    }
+}

+ 11 - 0
src/Vitorm/IDbSet.cs

@@ -0,0 +1,11 @@
+using Vitorm.Entity;
+
+namespace Vitorm
+{
+    public interface IDbSet
+    {
+        IEntityDescriptor entityDescriptor { get; }
+        IEntityDescriptor ChangeTable(string tableName);
+        IEntityDescriptor ChangeTableBack();
+    }
+}

+ 69 - 0
src/Vitorm/Sql/DbConnectionProvider.cs

@@ -0,0 +1,69 @@
+using System;
+using System.Data;
+
+namespace Vitorm.Sql
+{
+    public class DbConnectionProvider
+    {
+        protected DbConnectionProvider() { }
+        public DbConnectionProvider(
+            Func<string, IDbConnection> createDbConnection,
+            Func<string, string, string> changeDatabaseForConnectionString,
+            Func<string, string> getDatabaseName,
+            string connectionString,
+            string readOnlyConnectionString
+            )
+        {
+            this.createDbConnection = createDbConnection;
+            this.changeDatabaseForConnectionString = changeDatabaseForConnectionString;
+            this.getDatabaseName = getDatabaseName;
+            this.connectionString = connectionString;
+            this.readOnlyConnectionString = readOnlyConnectionString;
+        }
+
+
+        protected readonly string connectionString;
+        protected readonly string readOnlyConnectionString;
+
+        protected Func<string, IDbConnection> createDbConnection;
+
+        /// <summary>
+        ///  (string connectionString, string databaseName) => (string connectionStringWithNewDatabase)
+        /// </summary>
+        protected Func<string, string, string> changeDatabaseForConnectionString;
+
+        /// <summary>
+        ///  (string connectionString) => (string databaseName)
+        /// </summary>
+        protected Func<string, string> getDatabaseName;
+
+        public virtual bool ableToCreateReadOnly => readOnlyConnectionString != null;
+
+        public virtual string dbHashCode => connectionString.GetHashCode().ToString();
+
+
+        public IDbConnection CreaeteDbConnection() => createDbConnection(connectionString);
+        public IDbConnection CreateReadOnlyDbConnection() => ableToCreateReadOnly ? createDbConnection(readOnlyConnectionString) : null;
+
+        public virtual string databaseName => getDatabaseName(connectionString ?? readOnlyConnectionString);
+
+        public virtual DbConnectionProvider WithDatabase(string databaseName)
+        {
+            if (changeDatabaseForConnectionString == null) throw new InvalidOperationException("do not able to change database.");
+
+            var _connectionString = connectionString;
+            var _readOnlyConnectionString = readOnlyConnectionString;
+
+            if (_connectionString != null) _connectionString = changeDatabaseForConnectionString(_connectionString, databaseName);
+            if (_readOnlyConnectionString != null) _readOnlyConnectionString = changeDatabaseForConnectionString(_readOnlyConnectionString, databaseName);
+
+            return new DbConnectionProvider(
+                createDbConnection, changeDatabaseForConnectionString, getDatabaseName,
+                _connectionString, _readOnlyConnectionString
+                );
+        }
+
+
+
+    }
+}

+ 18 - 26
src/Vitorm/Sql/SqlDbContext.cs

@@ -38,8 +38,6 @@ namespace Vitorm.Sql
         }
 
 
-        protected Func<IDbConnection> createDbConnection { get; set; }
-        protected Func<IDbConnection> createReadOnlyDbConnection { get; set; }
         protected IDbConnection _dbConnection;
         protected IDbConnection _readOnlyDbConnection;
         public override void Dispose()
@@ -72,43 +70,42 @@ namespace Vitorm.Sql
                 }
             }
         }
-        public virtual IDbConnection dbConnection => _dbConnection ??= createDbConnection();
+        public virtual IDbConnection dbConnection => _dbConnection ??= dbConnectionProvider.CreaeteDbConnection();
         public virtual IDbConnection readOnlyDbConnection
-        {
-            get
-            {
-                if (_readOnlyDbConnection != null) return _readOnlyDbConnection;
-                if (createReadOnlyDbConnection != null) return _readOnlyDbConnection = createReadOnlyDbConnection();
-
-                return dbConnection;
-            }
-        }
+            => _readOnlyDbConnection ??
+                (dbConnectionProvider.ableToCreateReadOnly ? (_readOnlyDbConnection = dbConnectionProvider.CreateReadOnlyDbConnection()) : dbConnection);
 
 
         public virtual ISqlTranslateService sqlTranslateService { get; private set; }
 
 
+        protected DbConnectionProvider dbConnectionProvider;
 
+        /// <summary>
+        /// to identify whether contexts are from the same database
+        /// </summary>
+        protected virtual string dbGroupName => "SqlDbSet_" + dbConnectionProvider.dbHashCode;
+        public virtual string databaseName => dbConnectionProvider.databaseName;
 
         /// <summary>
         /// 
         /// </summary>
         /// <param name="sqlTranslateService"></param>
-        /// <param name="createDbConnection"></param>
-        /// <param name="createReadOnlyDbConnection"></param>
+        /// <param name="dbConnectionProvider"></param>
         /// <param name="sqlExecutor"></param>
-        /// <param name="dbHashCode"> to identify whether contexts are from the same database </param>
-        public virtual void Init(ISqlTranslateService sqlTranslateService, Func<IDbConnection> createDbConnection, Func<IDbConnection> createReadOnlyDbConnection = null, SqlExecutor sqlExecutor = null, string dbHashCode = null)
+        public virtual void Init(ISqlTranslateService sqlTranslateService, DbConnectionProvider dbConnectionProvider, SqlExecutor sqlExecutor = null)
         {
             this.sqlTranslateService = sqlTranslateService;
-            this.createDbConnection = createDbConnection;
-            this.createReadOnlyDbConnection = createReadOnlyDbConnection;
+            this.dbConnectionProvider = dbConnectionProvider;
             this.sqlExecutor = sqlExecutor ?? SqlExecutor.Instance;
+        }
+
 
-            if (string.IsNullOrEmpty(dbHashCode))
-                dbHashCode = GetHashCode().ToString();
+        public virtual void ChangeDatabase(string databaseName)
+        {
+            if (_dbConnection != null || _readOnlyDbConnection != null) throw new InvalidOperationException("cna not change database after connected, please try in an new DbContext.");
 
-            dbGroupName = "SqlDbSet_" + dbHashCode;
+            dbConnectionProvider = dbConnectionProvider.WithDatabase(databaseName);
         }
 
 
@@ -279,11 +276,6 @@ namespace Vitorm.Sql
 
         }
 
-
-        /// <summary>
-        /// to identify whether contexts are from the same database
-        /// </summary>
-        protected string dbGroupName { get; set; }
         protected bool QueryIsFromSameDb(object query, Type elementType)
         {
             return dbGroupName == QueryableBuilder.GetQueryConfig(query as IQueryable) as string;

+ 11 - 6
test/Vitorm.MySql.MsTest/DataSource.cs

@@ -56,15 +56,23 @@ namespace Vitorm.MsTest
         public static void WaitForUpdate() { }
 
         static readonly string connectionString = Appsettings.json.GetStringByPath("Vitorm.MySql.connectionString");
-        public static SqlDbContext CreateDbContextForWriting() => CreateDbContext();
+        public static SqlDbContext CreateDbContextForWriting(bool autoInit = true) => CreateDbContext(autoInit);
 
-        public static SqlDbContext CreateDbContext()
+        public static SqlDbContext CreateDbContext(bool autoInit = true)
         {
             var dbContext = new SqlDbContext();
             dbContext.UseMySql(connectionString);
 
-            dbContext.BeginTransaction();
+            //dbContext.BeginTransaction();
 
+            if (autoInit)
+                InitDbContext(dbContext);
+
+            return dbContext;
+        }
+
+        public static void InitDbContext(SqlDbContext dbContext)
+        {
             #region #1 init User
             {
                 dbContext.Drop<User>();
@@ -100,9 +108,6 @@ namespace Vitorm.MsTest
                 dbContext.AddRange(UserClass.NewClasses(1, 6));
             }
             #endregion
-
-
-            return dbContext;
         }
 
     }

+ 11 - 5
test/Vitorm.SqlServer.MsTest/DataSource.cs

@@ -58,15 +58,23 @@ namespace Vitorm.MsTest
 
         static string connectionString = Appsettings.json.GetStringByPath("Vitorm.SqlServer.connectionString");
 
-        public static SqlDbContext CreateDbContextForWriting() => CreateDbContext();
+        public static SqlDbContext CreateDbContextForWriting(bool autoInit = true) => CreateDbContext(autoInit);
 
-        public static SqlDbContext CreateDbContext()
+        public static SqlDbContext CreateDbContext(bool autoInit = true)
         {
             var dbContext = new SqlDbContext();
             dbContext.UseSqlServer(connectionString);
 
-            dbContext.BeginTransaction();
+            //dbContext.BeginTransaction();
 
+            if (autoInit)
+                InitDbContext(dbContext);
+
+            return dbContext;
+        }
+
+        public static void InitDbContext(SqlDbContext dbContext)
+        {
             #region #1 init User
             {
                 dbContext.Drop<User>();
@@ -100,8 +108,6 @@ namespace Vitorm.MsTest
                 dbContext.AddRange(UserClass.NewClasses(1, 6));
             }
             #endregion
-
-            return dbContext;
         }
 
     }

+ 80 - 0
test/Vitorm.Sqlite.MsTest/CommonTest/ChangeDatabase_Test.cs

@@ -0,0 +1,80 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace Vitorm.MsTest.CommonTest
+{
+
+    [TestClass]
+    public partial class ChangeDatabase_Test
+    {
+
+        [TestMethod]
+        public void Test_ChangeDatabase()
+        {
+            string databaseName;
+
+            // database
+            {
+                using var dbContext = DataSource.CreateDbContextForWriting(autoInit: false);
+
+                databaseName = dbContext.databaseName;
+
+                dbContext.Drop<User>();
+                dbContext.Create<User>();
+
+                var user = dbContext.Get<User>(1);
+                Assert.IsNull(user);
+
+                user = User.NewUser(id: 1, forAdd: true);
+                user.name = "Hello database";
+                dbContext.Add(user);
+            }
+
+            // database2
+            {
+                using var dbContext = DataSource.CreateDbContextForWriting(autoInit: false);
+
+                dbContext.ChangeDatabase(databaseName + "2");
+
+                dbContext.Drop<User>();
+                dbContext.Create<User>();
+
+                var user = dbContext.Get<User>(1);
+                Assert.IsNull(user);
+
+                user = User.NewUser(id: 1, forAdd: true);
+                user.name = "Hello database2";
+                dbContext.Add(user);
+            }
+
+
+            DataSource.WaitForUpdate();
+
+            // database
+            {
+                using var dbContext = DataSource.CreateDbContextForWriting(autoInit: false);
+
+                dbContext.ChangeDatabase(databaseName);
+                var user = dbContext.Get<User>(1);
+                Assert.AreEqual("Hello database", user.name);
+            }
+
+            // database2
+            {
+                using var dbContext = DataSource.CreateDbContextForWriting(autoInit: false);
+
+                dbContext.ChangeDatabase(databaseName + "2");
+
+                var user = dbContext.Get<User>(1);
+                Assert.AreEqual("Hello database2", user.name);
+            }
+
+
+        }
+
+
+
+
+
+
+    }
+}

+ 71 - 0
test/Vitorm.Sqlite.MsTest/CommonTest/ChangeTable_Test.cs

@@ -0,0 +1,71 @@
+using System.Data;
+
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace Vitorm.MsTest.CommonTest
+{
+
+    [TestClass]
+    public partial class ChangeTable_Test
+    {
+
+        [TestMethod]
+        public void Test_ChangeTable()
+        {
+            string tableName;
+
+            using var dbContext = DataSource.CreateDbContextForWriting();
+
+            var dbSet = dbContext.DbSet<User>();
+            tableName = dbSet.entityDescriptor.tableName;
+            User user;
+
+            // User
+            {
+                user = dbSet.Get(1);
+                Assert.IsNotNull(user);
+            }
+
+            // User2
+            {
+                dbSet.ChangeTable(tableName + "2");
+
+                dbSet.Drop();
+                dbSet.Create();
+
+                user = dbSet.Get(1);
+                Assert.IsNull(user);
+
+                var users = User.NewUsers(startId: 1, count: 5, forAdd: true);
+                user = users[1];
+                user.name = "Hello User2";
+                dbSet.AddRange(users);
+
+                dbSet.DeleteByKey(1);
+
+            }
+
+            DataSource.WaitForUpdate();
+
+            // Assert User2
+            {
+                var userList = dbSet.Query().Where(user => new[] { 1, 2, 3 }.Contains(user.id)).OrderBy(u => u.id).ToList();
+
+                Assert.AreEqual(2, userList.Count);
+                Assert.AreEqual(2, userList[0].id);
+                Assert.AreEqual("Hello User2", userList[0].name);
+            }
+
+            // Assert User
+            {
+                //dbSet.ChangeTableBack();
+                dbSet.ChangeTable(tableName);
+                Assert.AreEqual("u246", dbSet.Get(2)?.name);
+            }
+
+        }
+
+
+
+    }
+}

+ 12 - 6
test/Vitorm.Sqlite.MsTest/DataSource.cs

@@ -7,7 +7,7 @@ namespace Vitorm.MsTest
     {
         public User() { }
 
-        public User(int nid) { id = nid; }
+        public User(int id) { this.id = id; }
         public User(string name) { this.name = name; }
 
 
@@ -57,8 +57,8 @@ namespace Vitorm.MsTest
     {
         public static void WaitForUpdate() { }
 
-        public static SqlDbContext CreateDbContextForWriting() => CreateDbContext();
-        public static SqlDbContext CreateDbContext()
+        public static SqlDbContext CreateDbContextForWriting(bool autoInit = true) => CreateDbContext(autoInit);
+        public static SqlDbContext CreateDbContext(bool autoInit = true)
         {
             var guid = Guid.NewGuid().ToString();
             var filePath = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, $"{guid}.sqlite.db");
@@ -67,9 +67,17 @@ namespace Vitorm.MsTest
             var dbContext = new SqlDbContext();
             dbContext.UseSqlite(connectionString);
 
-            dbContext.BeginTransaction();
+            //dbContext.BeginTransaction();
 
+            if (autoInit)
+                InitDbContext(dbContext);
 
+            return dbContext;
+        }
+
+
+        public static void InitDbContext(SqlDbContext dbContext)
+        {
             #region #1 init User
             {
                 dbContext.Drop<User>();
@@ -100,8 +108,6 @@ namespace Vitorm.MsTest
                 dbContext.AddRange(UserClass.NewClasses(1, 6));
             }
             #endregion
-
-            return dbContext;
         }
 
     }