简体中文
LibrameTick.Extensions 是一个基于 .NET 7 的基础框架系列库,也是针对原 Librame.Extensions 系列库重构而成的下一代基础框架系列库。本系列库主要包括 LibrameTick.Extensions 基础扩展和基于基础扩展开发的包括 LibrameTick.Extensions.Core 核心、LibrameTick.Extensions.Data.EntityFrameworkCore 数据、LibrameTick.Extensions.Drawing.SkiaSharp 图画等四个基本扩展库。
本系列库在保留上一代功能的基础上,相对于上一代做了尽可能多的精简和优化,将上一代中的 Librame.Extensions.Encryption 加密、Librame.Extensions.Network 网络、Librame.Extensions.Storage 存储等基本扩展库的功能整合进了核心基本扩展库,将数据基本扩展库的大多数接口和抽象功能整合进了基本扩展库中,使得本代框架系列库在功能上的设计更为合理;同时利用 .NET 7 的新特性,在性能上做了尽可能多的优化,使得本代框架系列库在性能上得到了较大提升。
LibrameTick.Extensions APIs 可以使用 NuGet 包管理器添加到项目中。官方发布在 NuGet 上。
参见 上一代 基础框架系列库功能特性。
以 Librame.Extensions.Data.EntityFrameworkCore 数据扩展库为例(目前支持多库读写集群,暂不支持分库分表功能):
PM> Install-Package: Librame.Extensions.Data.EntityFrameworkCore
将单个应用程序项目的 MySQL、SQLServer、SQLite 三种数据库配置为实时异库集群,其中将 MySQL、SQLServer 二种数据库配置为冗余写入,SQLite、SQLServer 二种数据库配置为冗余读取,在 SQLite 读取异常时会自行切换到 SQLServer 库。具体配置如下:
var services = new ServiceCollection();
services.AddDbContext<TestSqlServerDbContext>(opts =>
{
opts.UseSqlServer("Data Source=.;Initial Catalog=librame_extensions;Integrated Security=true;TrustServerCertificate=true;",
a => a.MigrationsAssembly(modelAssemblyName));
opts.UseAccessor(b => b.WithAccess(AccessMode.ReadWrite).WithSharding<DateTimeOffsetShardingStrategy>("%ww").WithPriority(3).WithLocalhostLoader());
});
services.AddDbContext<TestMySqlDbContext>(opts =>
{
opts.UseMySql(MySqlConnectionStringHelper.Validate("server=localhost;port=3306;database=librame_extensions;user=root;password=123456;", out var version), version,
a => a.MigrationsAssembly(modelAssemblyName));
opts.UseAccessor(b => b.WithAccess(AccessMode.Write).WithSharding<DateTimeOffsetShardingStrategy>("%ww").WithPriority(2).WithLocalhostLoader());
});
// SQLite 不支持事务,不推荐用于集群中(至少不做为写入库),即使用在集群中,在使用事务时会捕获到异常而切换到下一个数据库上下文
services.AddDbContext<TestSqliteDbContext>(opts =>
{
opts.UseSqlite("Data Source=librame_extensions.db",
a => a.MigrationsAssembly(modelAssemblyName));
opts.UseAccessor(b => b.WithAccess(AccessMode.Read).WithSharding<DateTimeOffsetShardingStrategy>("%ww").WithPriority(1).WithLocalhostLoader());
});
services.AddLibrame()
.AddData()
.AddAccessor(typeof(BaseAccessor<>), autoReferenceDbContext: true)
.AddInitializer<InternalTestAccessorInitializer>()
.AddSeeder<InternalTestAccessorSeeder>();
//.SaveOptionsAsJson(); // 首次保存选项为 JSON 文件
var provider = services.BuildServiceProvider();
using (var scope = _rootProvider.CreateScope())
{
var provider = scope.ServiceProvider;
// 使用访问器初始化器按数据库集群初始化种子数据
provider.UseAccessorInitializer();
var userStore = provider.GetRequiredService<IStore<User>>();
Assert.NotNull(userStore);
var pagingUsers = userStore.FindPagingList(p => p.PageByIndex(index: 1, size: 5));
Assert.NotNull(pagingUsers);
// sql=$"SELECT * FROM {userStore.GetTableName()}"
var sqlUsers = userStore.QueryBySql("SELECT * FROM ${Table}").ToList();
Assert.NotEmpty(sqlUsers);
// Update
foreach (var user in pagingUsers)
{
user.Name = $"Update {user.Name}";
}
// 仅针对写入访问器
userStore.Update(pagingUsers);
// Add
var addUsers = new User[10];
for (var i = 0; i < 10; i++)
{
var user = new User
{
Name = $"Add Name {i + 1}",
Passwd = "123456"
};
user.Id = userStore.IdGeneratorFactory.GetMongoIdGenerator().GenerateId();
user.PopulateCreation(pagingUsers.First().Id, DateTimeOffset.UtcNow);
addUsers[i] = user;
}
// 仅针对写入访问器
userStore.Add(addUsers);
userStore.SaveChanges();
// 读取访问器(SQLite/SQLServer)
var users = userStore.FindList(p => p.Name!.StartsWith("Update"));
Assert.NotNull(users); // 默认 SQLite 无更新数据且不支持事务,所以会捕获到异常并自动切换到 SQLServer 读取数据
// 强制从写入访问器(MySQL/SQLServer)
users = userStore.UseWriteAccessor().FindList(p => p.Name!.StartsWith("Update"));
Assert.NotNull(users); // 默认 MySQL 有更新数据
// 读取访问器(SQLite/SQLServer)
users = userStore.UseReadAccessor().FindList(p => p.Name!.StartsWith("Add"));
Assert.NotNull(users); // 默认 SQLite 无更新数据且不支持事务,所以会捕获到异常并自动切换到 SQLServer 读取数据
// 强制从写入访问器(MySQL/SQLServer)
users = userStore.UseWriteAccessor().FindList(p => p.Name!.StartsWith("Add"));
Assert.NotNull(users); // 默认 MySQL 有新增数据
// 使用名称获取指定访问器(默认名称为 TestSqlServerDbContext[-DbContext])
pagingUsers = userStore.UseAccessor("TestSqlServer").FindPagingList(p => p.PageByIndex(index: 1, size: 10));
Assert.NotNull(pagingUsers);
}
以上功能在本库的测试项目中测试通过,详情请参见TestAccessorTests 。