数据上下文dbcontext添加数据与Database数据库的分库分表,表映射,切换表,使用到了IModelCacheKeyFactory代码如下:

数据上下文dbcontext添加数据与Database数据库的分库分表,表映射,切换表,使用到了IModelCacheKeyFactory

代码如下:

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace EFCOREDB
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            #region 测试
            TestDBContext(); 
            #endregion
            Console.Read();
        }
        
        #region Database数据库操作
        /// <summary>
        /// 测试数据库的分库分表,表映射,切换表
        /// </summary>
        static void TestDBContext()
        {
            #region DBContext
            //DateTime datetime1 = DateTime.Now;
            //using (var context = new DynamicContext { CreateDateTime = datetime1 })
            //{
            //    Console.WriteLine("开始删除数据库");
            //    context.Database.EnsureDeleted();
            //    Console.WriteLine("删除成功");
            //    Console.WriteLine("开始创建数据库");
            //    context.Database.EnsureCreated();
            //    Console.WriteLine("创建成功");
            //    var tablename = context.Model.FindEntityType(typeof(Test)).GetTableName();
            //    #region MyRegion
            //    //context.Tests.Add(new Test { Title = "Great News One", Content = $"Hello World! I am the news of {datetime1}", CreateDateTime = datetime1 });
            //    //更新实体的方式
            //    //0、查询实体,修改实体字段,context.SaveChanges();
            //    //1、创建实体,context.Entry(创建的实体).State=EntityState.Modified; context.SaveChanges();
            //    //2、创建实体,context.Update(创建的实体); context.SaveChanges();
            //    //3、创建实体,context.DbSet<Test>.Attach(创建的实体); context.Entry(创建的实体).State=EntityState.Modified; context.SaveChanges();
            //    //3、创建实体,context.DbSet<Test>.Attach(创建的实体); context.ChangeTracker.DetectChanges(); context.SaveChanges();
            //    //3、创建实体,context.Attach(创建的实体); context.Entry(创建的实体).State=EntityState.Modified; context.SaveChanges();
            //    //4、context.ChangeTracker.TrackGraph(ss, e => {
            //    //    if ((e.Entry.Entity as Test) != null)
            //    //    {
            //    //        e.Entry.State = EntityState.Unchanged;
            //    //    }
            //    //    else
            //    //    {
            //    //        e.Entry.State = EntityState.Modified;
            //    //    }
            //    //});
            //    //context.SaveChanges(); 
            //    #endregion

            //    var ss = new Test { Title = "11", Content = $"111 {datetime1}", CreateDateTime = datetime1 };
            //    Console.WriteLine($"context.Entry(ss).State:{context.Entry(ss).State}");
            //    //context.Attach(ss);//告诉EF Core开始跟踪person实体的更改,因为调用DbContext.Attach方法后,EF Core会将person实体的State值(可以通过testDBContext.Entry(ss).State查看到)更改回EntityState.Unchanged,所以这里testDBContext.Attach(ss)一定要放在下面一行testDBContext.Entry(ss).Property(p => p.Content).IsModified = true的前面,否者后面的testDBContext.SaveChanges方法调用后,数据库不会被更新
            //    //context.Entry(ss).Property(p => p.Content).IsModified = true;//告诉EF Core实体ss的Content属性已经更改。将testDBContext.Entry(person).Property(p => p.Name).IsModified设置为true后,也会将ss实体的State值(可以通过testDBContext.Entry(ss).State查看到)更改为EntityState.Modified,这样就保证了下面SaveChanges的时候会将ss实体的Content属性值Update到数据库中。
            //    //context.Entry(ss).Property(p => p.Content).IsModified = true;
            //    //context.Tests.Attach(ss);
            //    context.Attach(ss);
            //    Console.WriteLine($"context.Entry(ss).State:{context.Entry(ss).State}");
            //    //context.ChangeTracker.DetectChanges();
            //    context.SaveChanges();
            //}

            ////切换表
            //DateTime datetime2 = DateTime.Now.AddDays(-1);
            //using (var context = new DynamicContext { CreateDateTime = datetime2 })
            //{
            //    var tablename = context.Model.FindEntityType(typeof(Test)).GetTableName();//查询实体映射到数据库中对应的表名称
            //    if (!tablename.Equals("20201118"))
            //    {
            //        //var str = GetMySQLSqls(datetime2);
            //        var str = GetSqlServerSqls(datetime2);

            //        //判断是否存在表,不存在则创建
            //        using var cmd = context.Database.GetDbConnection().CreateCommand();
            //        cmd.CommandText = str[0];
            //        if (cmd.Connection.State != System.Data.ConnectionState.Open)
            //        {
            //            cmd.Connection.Open();
            //        }
            //        var result = cmd.ExecuteScalar();
            //        if (result.ToString() == "0")
            //        {
            //            //创建新表
            //            context.Database.ExecuteSqlRaw(str[1]);
            //        }
            //    }

            //    //context.Database.EnsureCreated();
            //    context.Tests.Add(new Test { Title = "22", Content = $"222 {datetime2}", CreateDateTime = datetime2 });
            //    context.SaveChanges();
            //}

            //using (var context = new DynamicContext { CreateDateTime = datetime1 })
            //{
            //    var entity = context.Tests.Single();
            //    // Writes news of today
            //    Console.WriteLine($"{entity.Title} {entity.Content} {entity.CreateDateTime}");
            //}

            //using (var context = new DynamicContext { CreateDateTime = datetime2 })
            //{
            //    var entity = context.Tests.Single();
            //    // Writes news of yesterday
            //    Console.WriteLine($"{entity.Title} {entity.Content} {entity.CreateDateTime}");
            //} 
            #endregion
        }

        #region Database数据库操作
        private static string[] GetMySQLSqls(DateTime time)
        {
            string tableName = time.ToString("yyyyMMdd");
            string decide = $"SELECT count(1) FROM information_schema.TABLES WHERE table_name='{tableName}'";
            string sqlRaw = $@"
CREATE TABLE IF NOT EXISTS `{tableName}` (
  `Id` int(20) NOT NULL,
  `Title` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
  `Content` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
  `CreateDateTime` datetime(6) NOT NULL,
  PRIMARY KEY (`Id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
";
            return new string[] { decide, sqlRaw };
        }

        private static string[] GetSqlServerSqls(DateTime time)
        {
            //注意:[Id] int NOT NULL IDENTITY(1,1)中的 IDENTITY(1,1) 表示自增
            string tableName = time.ToString("yyyyMMdd");
            //-- 判断要创建的表名是否存在 select * from dbo.sysobjects where id=object_id(N'[dbo].[{0}]') and xtype='U'
            string decide = $"SELECT COUNT(1) FROM dbo.sysobjects WHERE id = object_id(N'[dbo].[{tableName}]') and OBJECTPROPERTY(id, N'IsUserTable') = 1";
            string sqlRaw = $@"IF NOT EXISTS ( SELECT * FROM dbo.sysobjects WHERE id=object_id(N'[dbo].[{tableName}]') AND xtype='U')
BEGIN
CREATE TABLE [dbo].[{tableName}] (
[Id] int NOT NULL IDENTITY(1,1),
[Title] nvarchar(20) NULL ,
[Content] nvarchar(500) NULL ,
[CreateDateTime] datetime2(7) NOT NULL ,
);
ALTER TABLE [dbo].[{tableName}] ADD PRIMARY KEY ([Id]);
END";
            return new string[] { decide, sqlRaw };
        }

        private static string[] GetOracleSqls(string defaultSchema, DateTime time)
        {
            string tableName = time.ToString("yyyyMMdd");
            string schema = defaultSchema;
            string id_seq = $"{tableName}_id_seq";
            var pk = $"PK_{tableName}";
            string decide = $"SELECT COUNT(1) FROM all_tables WHERE TABLE_NAME='{tableName}' AND OWNER='{schema}'";
            string sqlRaw =
$@"DECLARE num NUMBER;
BEGIN
    SELECT
        COUNT(1) INTO num 
    FROM
        all_tables 
    WHERE
        TABLE_NAME = '{tableName}' 
        AND OWNER = '{schema}';
    IF
        num = 0 THEN
            EXECUTE IMMEDIATE 'CREATE TABLE ""{schema}"".""{tableName}"" (
            ""Id"" NUMBER(10) NOT NULL,
            ""Title"" NVARCHAR2(20),
            ""Content"" NCLOB,
            ""CreateDateTime"" TIMESTAMP(7) NOT NULL,
            CONSTRAINT ""{pk}"" PRIMARY KEY(""Id""),
            )';

            EXECUTE IMMEDIATE 'CREATE SEQUENCE ""{schema}"".""{id_seq}"" START WITH 1 INCREMENT BY 1';
            END IF;
            END; ";
            return new string[] { decide, sqlRaw };
        }
        #endregion
        #endregion
    }
    public class Test
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }
        public DateTime CreateDateTime { get; set; }
    }
    public class DynamicContext : DbContext
    {
        public DateTime CreateDateTime { get; set; }//为了区分不同的表
        public DbSet<Test> Tests { get; set; }

        //sqlserver连接字符串 Server=(localdb)\mssqllocaldb;Database=DynamicContext;Trusted_Connection=True;
        //sqlserver连接字符串 server=127.0.0.1;database=DynamicContext;user=zy;password=zy;

        //oracle连接字符串 Data Source=127.0.0.1:1521/orcl;User Id=zy;Password=zy;
        //"DbConnectString": "Data Source=127.0.0.1:1521/orcl;User Id=zy;Password=zy;",
        //"DefaultSchema": "ZY", 
        //"DbVersion": "11", 

        //mysql连接字符串 server=127.0.0.1;database=DynamicContext;user=zy;password=zy;
        //public static string DbConnectString = "(localdb)\mssqllocaldb;Database=DynamicContext;Trusted_Connection=True;";
        //如果是oracle的话,Oracle连接字符串中并不包含数据名称,其实DefaultSchema就是数据库名称,音系需要下面的两个DefaultSchema,DbVersion字段
        public static string DefaultSchema = "ZY";//
        public static string DbVersion = "11";
        DbType dbType = DbType.SqlServer;

        #region OnConfiguring
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            switch (dbType)
            {
                case DbType.SqlServer:
                    string DbConnectStringSqlServer = "(localdb)\mssqllocaldb;Database=DynamicContext;Trusted_Connection=True;";
                    DbConnectStringSqlServer = "server=127.0.0.1;database=DynamicContext;user=zy;password=zy;";
                    DbConnectStringSqlServer = "server=127.0.0.1;database=DynamicContext;user=sa;password=sa123;";
                    optionsBuilder.UseSqlServer(DbConnectStringSqlServer)
                        .ReplaceService<IModelCacheKeyFactory, DynamicModelCacheKeyFactory>();
                    break;
                case DbType.MySql:
                    string DbConnectStringMySql = "server=127.0.0.1;database=DynamicContext;user=zy;password=zy;";
                    DbConnectStringMySql = "server=127.0.0.1;database=DynamicContext;user=root;password=123456;";
                    optionsBuilder.UseMySql(DbConnectStringMySql)
                        .ReplaceService<IModelCacheKeyFactory, DynamicModelCacheKeyFactory>();
                    break;
                case DbType.Oracle:
                    string DbConnectStringOracle = "Data Source=127.0.0.1:1521/orcl;User Id=zy;Password=zy;";
                    optionsBuilder.UseOracle(DbConnectStringOracle, t => t.UseOracleSQLCompatibility(DbVersion))
                        .ReplaceService<IModelCacheKeyFactory, DynamicModelCacheKeyFactory>();
                    break;
                default:
                    throw new Exception("数据库不匹配。。。");
            }
        }
        //=> optionsBuilder.UseMySql(DbConnectString).ReplaceService<IModelCacheKeyFactory, DynamicModelCacheKeyFactory>();
        //=> optionsBuilder.UseOracle(DbConnectString).ReplaceService<IModelCacheKeyFactory, DynamicModelCacheKeyFactory>();
        //=> optionsBuilder.UseSqlServer(DbConnectString).ReplaceService<IModelCacheKeyFactory, DynamicModelCacheKeyFactory>();


        //protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        //=> optionsBuilder.UseInMemoryDatabase("DynamicContext")
        //.ReplaceService<IModelCacheKeyFactory, DynamicModelCacheKeyFactory>();
        #endregion

        #region OnModelCreating
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            if (Database.IsOracle())
            {
                modelBuilder.HasDefaultSchema(DefaultSchema);
            }

            modelBuilder.Entity<Test>(b =>
            {
                b.ToTable(CreateDateTime.ToString("yyyyMMdd"));
                b.HasKey(p => p.Id);
                //b.Property(p => p.Id).HasColumnType("int").ValueGeneratedOnAdd();
                //b.Property(p => p.Id).HasColumnType("int");
                b.Property(p => p.Title).HasMaxLength(20);
                b.Property(p => p.Content).HasMaxLength(500);
            });
        }
        #endregion
    }
    public enum DbType
    {
        SqlServer,
        MySql,
        Oracle
    }

    public class DynamicModelCacheKeyFactory : IModelCacheKeyFactory
    {
        public object Create(DbContext context) => context is DynamicContext dynamicContext ? (context.GetType(), dynamicContext.CreateDateTime) : (object)context.GetType();
    }
}
龙腾一族至尊龙骑
原文地址:https://www.cnblogs.com/1175429393wljblog/p/15098321.html