欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

(四)数据持久化(基于YesSql)

程序员文章站 2023-10-16 20:50:05
ORM框架(持久化流程) session是事务 (transaction) 的工厂,处理session后,所有更改将自动刷新到数据库中。或者,如果要处理何时将更改刷新到数据库,即transaction将在session处理完后异步提交。session也可以取消事务。 新建两个项目,Data 与 Da ......

orm框架(持久化流程)

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

(四)数据持久化(基于YesSql)

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

(四)数据持久化(基于YesSql)

 

(四)数据持久化(基于YesSql)

 

 

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