基于EF Core存储的国际化服务
前言
.NET 官方有一个用来管理国际化资源的扩展包Microsoft.Extensions.Localization,ASP.NET Core也用这个来实现国际化功能。但是这个包的翻译数据是使用resx资源文件来管理的,这就意味着无法动态管理。虽然官方有在文档中提供了一些第三方管理方案,但是都不太方便。其中一个是基于Json文件的,虽然可以动态管理,但是正确的Key值有时很难猜对,特别是对于嵌套类和泛型类之类名字比较特殊的。另外两个基于EF Core的一个只是个demo;另一个已多年未更新,且上下文生命周期和并发管理有缺陷(这个库还是我提交pr才支持的 .NET 5)。最近项目有用到国际化功能,只好重新写一个。
新书宣传
有关新书的更多介绍欢迎查看《C#与.NET6 开发从入门到实践》上市,作者亲自来打广告了!

正文
这个扩展包代码不多也不算复杂,主要结构参考官方内置实现。对于 .NET 5以上支持上下文工厂的版本使用上下文工厂,而对于旧版本则创建内部作用域获取私有上下文,以此彻底避免并发问题。作用域和上下文都是需要查询时临时获取和使用,查询完数据立即销毁避免内存泄漏。如果使用池化上下文工厂性能会更好。
对代码感兴趣的朋友可以移步Github。这里直接介绍一下基本用法。
这个库分为三个包:抽象包定义了所需接口,实体模型包定义基本实体类型,功能包定义了服务接口的实现类和用于注册服务的扩展方法。方便为分离项目的解决方案按需引用,减少无关类型的污染。
以在ASP.NET Core中使用为例:
实体模型和上下文
public class YourLocalizationRecord : LocalizationRecord
{
public int YourProperty { get; set; }
}
public class YourDbContext : DbContext
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// 使用默认类型。
modelBuilder.UseLocalizationRecord();
// 使用自定义类型,需要继承LocalizationRecord。
modelBuilder.UseLocalizationRecord<YourLocalizationRecord>(b =>
{
b.Property(r => r.ResourceCulture).HasMaxLength(32);
b.ToTable($"{nameof(YourLocalizationRecord)}s");
});
}
}
服务注册
// 对于 .NET 5 以上请使用上下文工厂。
services.AddDbContextFactoty<YourDbContext>(options => options.UseSqlite("Localization.db"));
// 或者池化工厂也是一样的,而且更好。
services.AddPooledDbContextFactoty<YourDbContext>(options => options.UseSqlite("Localization.db"));
// 注册一个自定义工厂服务模拟作用域上下文服务
services.AddScoped<YourDbContext>(sp => sp.GetRequiredService<IDbContextFactory<YourDbContext>>().CreateDbContext());
// 对于 .NETStandard 2.0 或 2.1 请使用上下文。
services.AddDbContext<YourDbContext>(options => options.UseSqlite("Localization.db"));
// 注册使用默认实体类型的服务。
services.AddEntityFrameworkCoreLocalization<YourDbContext>(options =>
{
options.ResourcesPath = "Resources";
// 是否自动创建缺失的资源记录
options.CreateLocalizationResourcesIfNotExist = true;
});
// 注册使用自定义实体类型的服务。
services.AddEntityFrameworkCoreLocalization<YourDbContext, YourLocalizationRecord>(options =>
{
options.ResourcesPath = "Resources";
// 是否自动创建缺失的资源记录
options.CreateLocalizationResourcesIfNotExist = true;
});
其他的和官方文档用法完全一致,如果需要清除缓存使资源能在下次读取时更新,可以使用服务IDynamicResourceStringLocalizerFactory。这个服务继承自内置服务,获取的IStringLocalizerFactory服务实际上也是IDynamicResourceStringLocalizerFactory的实现。
既然已经有上下文了,想怎么读写数据应该不必多言了吧。实体类的属性LocalizedContent就是翻译后的文本。如果使用自动创建记录,只需要查找所有这个属性为null的记录并翻译保存,最后清除缓存即可。

结语
为了实现对 .NETStantard 2.0 的兼容代码上使用了条件编译预处理实现一份代码一个项目同时编译到所有框架,最大程度共用代码简化代码管理。
附上国际化官方文档:使 ASP.NET Core 应用内容可本地化,在本地化 ASP.NET Core 应用中为每个请求选择语言/区域性
许可证:MIT
代码仓库:CoreDX.Extensions.Localization.EntityFrameworkCore - Github
Nuget:CoreDX.Extensions.Localization.EntityFrameworkCore
Nuget:CoreDX.Extensions.Localization.EntityFrameworkCore.Abstractions
Nuget:CoreDX.Extensions.Localization.EntityFrameworkCore.Models
QQ群
读者交流QQ群:540719365

欢迎读者和广大朋友一起交流,如发现本书错误也欢迎通过博客园、QQ群等方式告知笔者。
本文地址:https://www.cnblogs.com/coredx/p/18294729.html
基于EF Core存储的国际化服务的更多相关文章
- C# 嵌入dll 动软代码生成器基础使用 系统缓存全解析 .NET开发中的事务处理大比拼 C#之数据类型学习 【基于EF Core的Code First模式的DotNetCore快速开发框架】完成对DB First代码生成的支持 基于EF Core的Code First模式的DotNetCore快速开发框架 【懒人有道】在asp.net core中实现程序集注入
C# 嵌入dll 在很多时候我们在生成C#exe文件时,如果在工程里调用了dll文件时,那么如果不加以处理的话在生成的exe文件运行时需要连同这个dll一起转移,相比于一个单独干净的exe,这种形 ...
- 基于EF Core的Code First模式的DotNetCore快速开发框架
前言 最近接了几个小单子,因为是小单子,项目规模都比较小,业务相对来说,也比较简单.所以在选择架构的时候,考虑到效率方面的因素,就采取了asp.net+entity framework中的code f ...
- 【基于EF Core的Code First模式的DotNetCore快速开发框架】完成对DB First代码生成的支持
前言 距离上一篇文章<基于EF Core的Code First模式的DotNetCore快速开发框架>已过去大半个年头,时光荏苒,岁月如梭...比较尴尬的是,在这大半个年头里,除了日常带娃 ...
- .net Core 基于EF Core 实现数据库上下文
在做项目时,需要将某一些功能的实体建立在另一个数据库中,连接不同的数据库用以存储记录.通过查找资料,实现EF Core上下文. 下面是实现上下文后的解决方案的目录: 1.UpAndDownDbCont ...
- 基于ef core 2.0的数据库增删改审计系统
1.首先是建审计存储表 CREATE TABLE [dbo].[Audit] ( [Id] [uniqueidentifier] NOT NULL, [EntityName] [nvarchar](1 ...
- 统一流控服务开源:基于.Net Core的流控服务
先前有一篇博文,梳理了流控服务的场景.业界做法和常用算法 统一流控服务开源-1:场景&业界做法&算法篇 最近完成了流控服务的开发,并在生产系统进行了大半年的验证,稳定可靠.今天整理一下 ...
- 使用Asp.Net Core MVC 开发项目实践[第四篇:基于EF Core的扩展2]
上篇我们说到了基于EFCore的基础扩展,这篇我们讲解下基于实体结合拉姆达表达式的自定义更新以及删除数据. 先说下原理:其实通过实体以及拉姆达表达式生成SQL语句去执行 第一种更新扩展: 自定义更新字 ...
- 使用Asp.Net Core MVC 开发项目实践[第三篇:基于EF Core的扩展]
上篇我们说到了EFCore的基础使用,这篇我们将讲解下基于EFCore的扩展. 我们在Mango.Framework.EFCore类库项目中创建一个类名EFExtended的扩展类,并且引入相关的命名 ...
- Net Core的流控服务
统一流控服务开源:基于.Net Core的流控服务 先前有一篇博文,梳理了流控服务的场景.业界做法和常用算法 统一流控服务开源-1:场景&业界做法&算法篇 最近完成了流控服务的开发 ...
- .Net Core Grpc Consul 实现服务注册 服务发现 负载均衡
本文是基于..net core grpc consul 实现服务注册 服务发现 负载均衡(二)的,很多内容是直接复制过来的,..net core grpc consul 实现服务注册 服务发现 负载均 ...
随机推荐
- 从XML配置角度理解Spring AOP
本文分享自华为云社区<Spring高手之路18--从XML配置角度理解Spring AOP>,作者: 砖业洋__. 1. Spring AOP与动态代理 1.1 Spring AOP和动态 ...
- 解析 ABP vNext 依赖注入实现【属性注入】的原理
前言 这几天闲来没事看看ABP vNext的文档和源码,关于关于依赖注入(属性注入)这块儿产生了兴趣. 我们都知道.Volo.ABP 依赖注入容器使用了第三方组件Autofac实现的.有三种注入方式, ...
- OpenStack 的 SR-IOV 虚拟机热迁移
目录 文章目录 目录 前言列表 前言 SR-IOV Pass-through 虚拟机热迁移的问题 基于 macvtap 层的 SR-IOV 虚拟机热迁移 Workaround SR-IOV Pass- ...
- 提升WordPress网站加载速度的8个小技巧
提升WordPress网站加载速度是至关重要的,它不仅可以提高用户体验,还有助于SEO排名.以下是提升WordPress网站加载速度的8个小技巧,希望能帮助到大家. 优化图片: 使用适当大小和格式的图 ...
- 使用 TortoiseGit 时,报 Access denied 错误
当输入正确的密码时,总是报如下错误: 解决方法: 然后弹出如下对话框: 然后编辑本地配置文件: 然后将红色框的SSH配置改为绿色框的 HTTP配置,点击保存,确定. 然后再进行拉取源码,先输入用户名, ...
- 阿里面试:NIO为什么会导致CPU100%?
在 Java 中总共有三种 IO 类型:BIO(Blocking I/O,阻塞I/O).NIO(Non-blocking I/O,非阻塞I/O)和 AIO(Asynchronous I/O,异步I/O ...
- .Net6 MiNiApi +EFCore6.0高B格操作的WebApi
编辑器的选择项目运行雏形EFCore6.0的使用实体创建:exFAT 文件系统原理详解
前言 exFAT是微软2006年推出的一种文件系统,距今已快二十年,相比于FAT16和FAT32,exFAT还是算年轻.exFAT一直是微软的一个专用文件系统,直到2019年微软发布它的规范,目前微软 ...
- Flutter(六):Flutter_Boost接入现有原生工程(iOS+Android)
本篇博客会介绍如何通过第三方插件Flutter_Boost实现接入原有工程. 如果不希望引入第三方插件,可以参考博客Flutter混合开发--接入现有原生工程(iOS+Android) 一.新建原生工 ...
- OC的引用计数
一.引用计数 引用计数是Objetive-C语言的内存管理机制,用于管理OC对象(通常指包含isa指针的结构体)的内存. 一个对象的引用计数为大于0的计数,表示这个对象被持有,不能被释放,当引用计数为 ...