(四)数据持久化(基于YesSql)
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)的更多相关文章
- python(四)数据持久化操作 文件存储
1.写入 导入pickle包 然后组织一个列表my_list,保存为pkl格式,可以是任意格式 在磁盘下回出现一个保存的文件 2.读取
- iOS中常用的四种数据持久化技术
iOS中的数据持久化方式,基本上有以下四种:属性列表 对象归档 SQLite3和Core Data 1.属性列表涉及到的主要类:NSUserDefaults,一般 [NSUserDefaults st ...
- iOS中常用的四种数据持久化方法简介
iOS中常用的四种数据持久化方法简介 iOS中的数据持久化方式,基本上有以下四种:属性列表.对象归档.SQLite3和Core Data 1.属性列表涉及到的主要类:NSUserDefaults,一般 ...
- 四种数据持久化方式(下) :SQLite3 和 Core Data
在上文,我们介绍了iOS开发中的其中2种数据持久化方式:属性列表.归档解档. 本节将继续介绍另外2种iOS持久化数据的方法:数据库 SQLite3.Core Data 的运用: 在本节,将通过对4个文 ...
- 几种.NET平台数据持久化框架介绍
原文连接:http://yuxnet.blog.163.com/blog/static/164863495201131532223362/ 在.NET平台下,关于数据持久层框架非常多,本文主要对如下几 ...
- iOS数据持久化-OC
沙盒详解 1.IOS沙盒机制 IOS应用程序只能在为该改程序创建的文件系统中读取文件,不可以去其它地方访问,此区域被成为沙盒,所以所有的非代码文件都要保存在此,例如图像,图标,声音,映像,属性列表,文 ...
- iOS 数据持久化(扩展知识:模糊背景效果和密码保护功能)
本篇随笔除了介绍 iOS 数据持久化知识之外,还贯穿了以下内容: (1)自定义 TableView,结合 block 从 ViewController 中分离出 View,轻 ViewControll ...
- iOS: 数据持久化方案
数据持久化方案(如果总结不到位,或者有误的地方,敬请斧正) 一.功能: 主要是将数据持久化到本地,减少对网络请求的次数,既节省了用户的流量,也增强了App的体验效果. 二.种类: plist存储:使 ...
- 深入理解iPhone数据持久化(手把手教你iphone开发 – 基础篇)
在所有的移动开发平台数据持久化都是很重要的部分:在j2me中是rms或保存在应用程序的目录中,在symbian中可以保存在相应的磁盘目录中和数据库中.symbian中因为权限认证的原因,在3rd上大多 ...
- docker-compose一键部署redis一主二从三哨兵模式(含密码,数据持久化)
本篇基于centos7服务器进行部署开发 一.拉取redis镜像,使用如下命令 docker pull redis 1.查看镜像是否拉取成功,使用如下命令 docker images 显示如下则证明拉 ...
随机推荐
- 转 - RPC调用和HTTP调用的区别
很长时间以来都没有怎么好好搞清楚RPC(即Remote Procedure Call,远程过程调用)和HTTP调用的区别,不都是写一个服务然后在客户端调用么?这里请允许我迷之一笑~Naive!本文简单 ...
- spark 源码分析之九--Spark RPC剖析之StreamManager和RpcHandler
StreamManager StreamManager类说明 StreamManager 官方说明如下: The StreamManager is used to fetch individual c ...
- 备战金九银十,Java研发面试题(Spring、MySQL、JVM、Mybatis、Redis、Tomcat)[带答案],刷起来!
八月在即,马上就是"金九银十",又是跳槽招聘季.咱们这行公认涨薪不如跳槽加的快.但不建议频繁跳槽,还是要学会融合团队,抓住每个机会提升技能. 苏先生在这里给大家整理了一套各大互联网 ...
- Java连接MySQL8.0以上版本数据库方式
MySQL 8.0 开始数据库相比常用的 5.X 版本发生了比较大的变化,我们在连接数据库的过程中许多地方也要发生一些变化. 总结一下,想要利用 mysql-connector-java 与 MySQ ...
- Web安全之CSRF攻击(转载)
CSRF是什么? CSRF(Cross Site Request Forgery),中文是跨站点请求伪造.CSRF攻击者在用户已经登录目标网站之后,诱使用户访问一个攻击页面,利用目标网站对用户的信任, ...
- Java性能权威指南读书笔记--之一
JIT(即时编译) 解释型代码:程序可移植,相同的代码在任何有适当解释器的机器上,都能运行,但是速度慢. 编译型代码:速度快,电视不同CPU平台的代码无法兼容. java则是使用java的编译器先将其 ...
- 后端小白的VUE入门笔记, 前端高能慎入
因为项目需要前后端分离,后端竟然不用控制view层了,页面的跳转后端不再干涉,(前端的vue经过打包后成了一张index.html) 后端只需要响应给前端json串就ok,其实这不是爽歪歪?但是觉得还 ...
- MySQL操作命令梳理(1)
一.索引 1.创建索引 索引的创建可以在CREATE TABLE语句中进行,也可以单独用CREATE INDEX或ALTER TABLE来给表增加索引.以下命令语句分别展示了如何创建主键索引(PRIM ...
- RGW 学习 前言
对于CEPH的学习已经有一段的时间了,最近的一段时间都是集中在RGW网关这一方面,所以准备将学习的过程以及源代码的分析,将以随笔的形式记录下来. 每天更新一章.
- 设计模式:与SpringMVC底层息息相关的适配器模式
目录 前言 适配器模式 1.定义 2.UML类图 3.实战例子 4.总结 SpringMVC底层的适配器模式 参考 前言 适配器模式是最为普遍的设计模式之一,它不仅广泛应用于代码开发,在日常生活里也很 ...