ORM框架(持久化流程)

session是事务 (transaction) 的工厂,处理session后,所有更改将自动刷新到数据库中。或者,如果要处理何时将更改刷新到数据库,即transaction将在session处理完后异步提交。session也可以取消事务。

新建两个项目,Data 与 Data.Abstractions, 其中 Data.Abstractions 为对外抽象接口(面向对象设计原则),并用Nuget添加程序包。

public interface IFeatureInfo
    {
        string Id { get; }
        string Name { get; }
        int Priority { get; }
        string Category { get; }
        string Description { get; }
        bool DefaultTenantOnly { get; }
        //IExtensionInfo Extension { get; }
        string[] Dependencies { get; }
    }

  

public interface IFeatureManager
    {
        IEnumerable<IFeatureInfo> GetFeatures();
        IEnumerable<IFeatureInfo> GetFeatures(string[] featureIdsToLoad);
        IEnumerable<IFeatureInfo> GetFeatureDependencies(string featureId);
        IEnumerable<IFeatureInfo> GetDependentFeatures(string featureId);
        IFeatureInfo GetFeatureForDependency(Type dependency);
        void TryAdd(Type type, IFeatureInfo feature);
    }

  

public class DatabaseProvider
    {
        public string Name { get; set; }
        public string Value { get; set; }
        public bool HasConnectionString { get; set; }
        public bool HasTablePrefix { get; set; }
        publi

  

/// <summary>
    /// 数据库迁移管理
    /// </summary>
    public interface IDataMigrationManager
    {
        /// <summary>
        ///返回具有至少一个数据迁移类的特性,并调用相应的升级方法
        /// </summary>
        Task<IEnumerable<string>> GetFeaturesThatNeedUpdateAsync();

        /// <summary>
        /// 运行所有需要更新的迁移。
        /// </summary>
        Task UpdateAllFeaturesAsync();

        /// <summary>
        /// 将数据库更新为指定功能的最新版本
        /// </summary>
        Task UpdateAsync(string feature);

        /// <summary>
        /// 将数据库更新为指定功能的最新版本
        /// </summary>
        Task UpdateAsync(IEnumerable<string> features);

        /// <summary>
        /// 执行脚本删除与该特性相关的任何信息
        /// </summary>
        /// <param name="feature"></param>
        Task Uninstall(string feature);
    }

  

public interface IDbConnectionAccessor
    {
        /// <summary>
        /// 创建数据库连接
        /// </summary>
        /// <returns></returns>
        DbConnection CreateConnection();
    }

  

/// <summary>
    /// 数据库迁移工具,封装YesSql功能,直接修改数据库结构
    /// </summary>
    public interface ISchemaBuilder
    {
        YesSql.Sql.ISchemaBuilder SchemaBuilder { get; set; }
    }

  

public static class DataAccess
    {
        public static IApplicationBuilder UseDataAccess(this IApplicationBuilder app)
        {
            return app.UseMiddleware<CommitSessionMiddleware>();
        }

        /// <summary>
        /// 添加数据库
        /// </summary>
        /// <param name="services"></param>
        /// <param name="databaseType">数据库类型,支持:SqlConnection,Sqlite,MySql,Postgres</param>
        /// <param name="connectionString">Sqlite为yessql.db文件所在路径,其他数据库为连接字符串</param>
        /// <param name="tablePrefix">表名前缀</param>
        /// <returns></returns>
        public static IServiceCollection AddDataAccess(this IServiceCollection services, string databaseType, string connectionString, string tablePrefix = null)
        {
            services.AddScoped<IDataMigrationManager, DataMigrationManager>();

            // Adding supported databases
            services.TryAddDataProvider(name: "Sql Server", value: "SqlConnection", hasConnectionString: true, hasTablePrefix: true, isDefault: false);
            services.TryAddDataProvider(name: "Sqlite", value: "Sqlite", hasConnectionString: false, hasTablePrefix: false, isDefault: true);
            services.TryAddDataProvider(name: "MySql", value: "MySql", hasConnectionString: true, hasTablePrefix: true, isDefault: false);
            services.TryAddDataProvider(name: "Postgres", value: "Postgres", hasConnectionString: true, hasTablePrefix: true, isDefault: false);

            // Configuring data access
            services.AddSingleton<IStore>(sp =>
            {
                IConfiguration storeConfiguration = new YesSql.Configuration();

                switch (databaseType)
                {
                    case "SqlConnection":
                        storeConfiguration
                            .UseSqlServer(connectionString, IsolationLevel.ReadUncommitted)
                            .UseBlockIdGenerator();
                        break;
                    case "Sqlite":
                        var databaseFolder = connectionString;
                        var databaseFile = Path.Combine(databaseFolder, "yessql.db");
                        Directory.CreateDirectory(databaseFolder);
                        storeConfiguration
                            .UseSqLite($"Data Source={databaseFile};Cache=Shared", IsolationLevel.ReadUncommitted)
                            .UseDefaultIdGenerator();
                        break;
                    case "MySql":
                        storeConfiguration
                            .UseMySql(connectionString, IsolationLevel.ReadUncommitted)
                            .UseBlockIdGenerator();
                        break;
                    case "Postgres":
                        storeConfiguration
                            .UsePostgreSql(connectionString, IsolationLevel.ReadUncommitted)
                            .UseBlockIdGenerator();
                        break;
                    default:
                        throw new ArgumentException("Unknown database type: " + databaseType);
                }

                if (!string.IsNullOrWhiteSpace(tablePrefix))
                {
                    storeConfiguration = storeConfiguration.SetTablePrefix(tablePrefix + "_");
                }

                var store = StoreFactory.CreateAsync(storeConfiguration).GetAwaiter().GetResult();
                var indexes = sp.GetServices<IIndexProvider>();

                store.RegisterIndexes(indexes);

                return store;
            });

            services.AddScoped(sp =>
            {
                var store = sp.GetService<IStore>();

                if (store == null)
                {
                    return null;
                }

                var session = store.CreateSession();

                var scopedServices = sp.GetServices<IIndexProvider>();

                session.RegisterIndexes(scopedServices.ToArray());

                var httpContext = sp.GetRequiredService<IHttpContextAccessor>()?.HttpContext;

                if (httpContext != null)
                {
                    httpContext.Items[typeof(YesSql.ISession)] = session;
                }

                return session;
            });

            services.AddTransient<IDbConnectionAccessor, DbConnectionAccessor>();

            return services;
        }
    }

    public class CommitSessionMiddleware
    {
        private readonly RequestDelegate _next;

        public CommitSessionMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext httpContext)
        {
            await _next.Invoke(httpContext);

            // Don't resolve to prevent instantiating one in case of static sites
            var session = httpContext.Items[typeof(YesSql.ISession)] as YesSql.ISession;

            if (session != null)
            {
                await session.CommitAsync();
            }
        }
    }

  

public static class DataProvider
    {
        public static IServiceCollection TryAddDataProvider(this IServiceCollection services, string name, string value, bool hasConnectionString, bool hasTablePrefix, bool isDefault)
        {
            for (var i = services.Count - 1; i >= 0; i--)
            {
                var entry = services[i];
                if (entry.ImplementationInstance != null)
                {
                    var databaseProvider = entry.ImplementationInstance as DatabaseProvider;
                    if (databaseProvider != null && String.Equals(databaseProvider.Name, name, StringComparison.OrdinalIgnoreCase))
                    {
                        services.RemoveAt(i);
                    }
                }
            }

            services.AddSingleton(new DatabaseProvider { Name = name, Value = value, HasConnectionString = hasConnectionString, HasTablePrefix = hasTablePrefix, IsDefault = isDefault });

            return services;
        }
    }

  

最新文章

  1. [原创]纯CSS3打造的3D翻页翻转特效
  2. AD设置板子原点
  3. 初学Java 精简知识点总结
  4. len字符串的长度
  5. linux 内核手动编译
  6. OpenGL ES 中Uniform块
  7. 谈FTP服务器攻击技术及其展望 (修改中)
  8. 手把手教你写电商爬虫-第三课 实战尚妆网AJAX请求处理和内容提取
  9. hibernate注解原理
  10. 为什么使用Hystrix?
  11. JavaSE:八种基本数据类型
  12. Codeforces 886E Maximum Element 组合数学 + dp
  13. 【Codeforces 526D】Om Nom and Necklace
  14. 个人作业——final
  15. python解析VOC的xml文件并转成自己需要的txt格式
  16. 七、vue语法补充二(动态组件 &amp; 异步组件、访问元素 &amp; 组件、混入)
  17. 在android中实现webview与javascript之间的交互(转)
  18. 练手THINKPHP5过程和bootstrap3.3.7
  19. 【刷题】BZOJ 3295 [Cqoi2011]动态逆序对
  20. 数据库连接池之C3P0

热门文章

  1. mysql添加外键失败解决方案
  2. jQuery入门二(DOM对象与jQuery对象互相转换)
  3. Linux学习(一)--VMware下Linux安装和配置
  4. jQuery写toTop(回到顶部)效果
  5. jboss反序列化漏洞复现(CVE-2017-7504)
  6. 前端笔记之React(六)ES6的Set和Map&amp;immutable和Ramda和lodash&amp;redux-thunk
  7. python 简单的实现文件内容去重
  8. Spring浅入浅出——不吹牛逼不装逼
  9. kube-proxy源码解析
  10. JS和C#.NET获取客户端IP