(四)数据持久化(基于YesSql)
2024-08-29 10:27:46
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; } }
最新文章
- [原创]纯CSS3打造的3D翻页翻转特效
- AD设置板子原点
- 初学Java 精简知识点总结
- len字符串的长度
- linux 内核手动编译
- OpenGL ES 中Uniform块
- 谈FTP服务器攻击技术及其展望 (修改中)
- 手把手教你写电商爬虫-第三课 实战尚妆网AJAX请求处理和内容提取
- hibernate注解原理
- 为什么使用Hystrix?
- JavaSE:八种基本数据类型
- Codeforces 886E Maximum Element 组合数学 + dp
- 【Codeforces 526D】Om Nom and Necklace
- 个人作业——final
- python解析VOC的xml文件并转成自己需要的txt格式
- 七、vue语法补充二(动态组件 &; 异步组件、访问元素 &; 组件、混入)
- 在android中实现webview与javascript之间的交互(转)
- 练手THINKPHP5过程和bootstrap3.3.7
- 【刷题】BZOJ 3295 [Cqoi2011]动态逆序对
- 数据库连接池之C3P0
热门文章
- mysql添加外键失败解决方案
- jQuery入门二(DOM对象与jQuery对象互相转换)
- Linux学习(一)--VMware下Linux安装和配置
- jQuery写toTop(回到顶部)效果
- jboss反序列化漏洞复现(CVE-2017-7504)
- 前端笔记之React(六)ES6的Set和Map&;immutable和Ramda和lodash&;redux-thunk
- python 简单的实现文件内容去重
- Spring浅入浅出——不吹牛逼不装逼
- kube-proxy源码解析
- JS和C#.NET获取客户端IP