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;
        }
    }

  

(四)数据持久化(基于YesSql)的更多相关文章

  1. python(四)数据持久化操作 文件存储

    1.写入 导入pickle包 然后组织一个列表my_list,保存为pkl格式,可以是任意格式 在磁盘下回出现一个保存的文件 2.读取

  2. iOS中常用的四种数据持久化技术

    iOS中的数据持久化方式,基本上有以下四种:属性列表 对象归档 SQLite3和Core Data 1.属性列表涉及到的主要类:NSUserDefaults,一般 [NSUserDefaults st ...

  3. iOS中常用的四种数据持久化方法简介

    iOS中常用的四种数据持久化方法简介 iOS中的数据持久化方式,基本上有以下四种:属性列表.对象归档.SQLite3和Core Data 1.属性列表涉及到的主要类:NSUserDefaults,一般 ...

  4. 四种数据持久化方式(下) :SQLite3 和 Core Data

    在上文,我们介绍了iOS开发中的其中2种数据持久化方式:属性列表.归档解档. 本节将继续介绍另外2种iOS持久化数据的方法:数据库 SQLite3.Core Data 的运用: 在本节,将通过对4个文 ...

  5. 几种.NET平台数据持久化框架介绍

    原文连接:http://yuxnet.blog.163.com/blog/static/164863495201131532223362/ 在.NET平台下,关于数据持久层框架非常多,本文主要对如下几 ...

  6. iOS数据持久化-OC

    沙盒详解 1.IOS沙盒机制 IOS应用程序只能在为该改程序创建的文件系统中读取文件,不可以去其它地方访问,此区域被成为沙盒,所以所有的非代码文件都要保存在此,例如图像,图标,声音,映像,属性列表,文 ...

  7. iOS 数据持久化(扩展知识:模糊背景效果和密码保护功能)

    本篇随笔除了介绍 iOS 数据持久化知识之外,还贯穿了以下内容: (1)自定义 TableView,结合 block 从 ViewController 中分离出 View,轻 ViewControll ...

  8. iOS: 数据持久化方案

    数据持久化方案(如果总结不到位,或者有误的地方,敬请斧正) 一.功能: 主要是将数据持久化到本地,减少对网络请求的次数,既节省了用户的流量,也增强了App的体验效果. 二.种类:  plist存储:使 ...

  9. 深入理解iPhone数据持久化(手把手教你iphone开发 – 基础篇)

    在所有的移动开发平台数据持久化都是很重要的部分:在j2me中是rms或保存在应用程序的目录中,在symbian中可以保存在相应的磁盘目录中和数据库中.symbian中因为权限认证的原因,在3rd上大多 ...

  10. docker-compose一键部署redis一主二从三哨兵模式(含密码,数据持久化)

    本篇基于centos7服务器进行部署开发 一.拉取redis镜像,使用如下命令 docker pull redis 1.查看镜像是否拉取成功,使用如下命令 docker images 显示如下则证明拉 ...

随机推荐

  1. java的System.currentTimeMillis()和System.nanoTime

    纳秒 ns(nanosecond):纳秒, 时间单位.一秒的10亿分之一,即等于10的负9次方秒.常用作 内存读写速度的单位,其前面数字越小则表示速度越快.   1纳秒=1000 皮秒   1纳秒 = ...

  2. HPU暑期集训积分赛1

    A. Nth power of n 单点时限: 1.0 sec 内存限制: 512 MB 求 nn 的个位数. 输入格式 多组输入,处理到文件结束.每组数据输入一个 n.(1≤n≤109) 输出格式 ...

  3. 【MySQL】服务无法启动(Mac)

    如图所示: 点击 Start MySQL Server 没反应-- 终端输入 mysql 命令时报错如下: ERROR 2002 (HY000): Can't connect to local MyS ...

  4. 【Android Studio】Gradle DSL method not found:'android()'

    如图所示: 参考:http://www.jianshu.com/p/d370d41fb7da 又遇到了这个问题: 参考:http://stackoverflow.com/questions/24204 ...

  5. 【Android】System.exit(0) 退出程序

    许多 Android 应用程序都是连续点击两下返回键时退出程序,代码如下: private long exitTime = 0; @Override public boolean onKeyDown( ...

  6. 读写properties文件

    1. 读properties文件 Properties props = new Properties(); try { InputStream in = new FileInputStream(&qu ...

  7. opencv图像直方图均衡化及其原理

    直方图均衡化是什么有什么用 先说什么是直方图均衡化,通俗的说,以灰度图为例,原图的某一个像素为x,经过某个函数变为y.形成新的图.新的图的灰度值的分布是均匀的,这个过程就叫直方图均衡化. 图像直方图均 ...

  8. Vector的一些事

    1.利用数组对vector进行初始化方法 当然有许多方法,这里就讲一种.原因简单,其他方式请参见这个博文:http://www.cplusplus.me/1112.html , , , , -}; v ...

  9. 关于 java中的换行符

    java中实现换行有以下3种方法: 1.使用java中的转义符"\r\n": String str="aaa"; str+="\r\n"; ...

  10. String——字符串

    首先看一下string的一部分源码吧 public final class String private final char value[]; 我们暂且只看这两行, 第一行String被final修 ...