前言

.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存储的国际化服务的更多相关文章

  1. 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,这种形 ...

  2. 基于EF Core的Code First模式的DotNetCore快速开发框架

    前言 最近接了几个小单子,因为是小单子,项目规模都比较小,业务相对来说,也比较简单.所以在选择架构的时候,考虑到效率方面的因素,就采取了asp.net+entity framework中的code f ...

  3. 【基于EF Core的Code First模式的DotNetCore快速开发框架】完成对DB First代码生成的支持

    前言 距离上一篇文章<基于EF Core的Code First模式的DotNetCore快速开发框架>已过去大半个年头,时光荏苒,岁月如梭...比较尴尬的是,在这大半个年头里,除了日常带娃 ...

  4. .net Core 基于EF Core 实现数据库上下文

    在做项目时,需要将某一些功能的实体建立在另一个数据库中,连接不同的数据库用以存储记录.通过查找资料,实现EF Core上下文. 下面是实现上下文后的解决方案的目录: 1.UpAndDownDbCont ...

  5. 基于ef core 2.0的数据库增删改审计系统

    1.首先是建审计存储表 CREATE TABLE [dbo].[Audit] ( [Id] [uniqueidentifier] NOT NULL, [EntityName] [nvarchar](1 ...

  6. 统一流控服务开源:基于.Net Core的流控服务

    先前有一篇博文,梳理了流控服务的场景.业界做法和常用算法 统一流控服务开源-1:场景&业界做法&算法篇 最近完成了流控服务的开发,并在生产系统进行了大半年的验证,稳定可靠.今天整理一下 ...

  7. 使用Asp.Net Core MVC 开发项目实践[第四篇:基于EF Core的扩展2]

    上篇我们说到了基于EFCore的基础扩展,这篇我们讲解下基于实体结合拉姆达表达式的自定义更新以及删除数据. 先说下原理:其实通过实体以及拉姆达表达式生成SQL语句去执行 第一种更新扩展: 自定义更新字 ...

  8. 使用Asp.Net Core MVC 开发项目实践[第三篇:基于EF Core的扩展]

    上篇我们说到了EFCore的基础使用,这篇我们将讲解下基于EFCore的扩展. 我们在Mango.Framework.EFCore类库项目中创建一个类名EFExtended的扩展类,并且引入相关的命名 ...

  9. Net Core的流控服务

    统一流控服务开源:基于.Net Core的流控服务   先前有一篇博文,梳理了流控服务的场景.业界做法和常用算法 统一流控服务开源-1:场景&业界做法&算法篇 最近完成了流控服务的开发 ...

  10. .Net Core Grpc Consul 实现服务注册 服务发现 负载均衡

    本文是基于..net core grpc consul 实现服务注册 服务发现 负载均衡(二)的,很多内容是直接复制过来的,..net core grpc consul 实现服务注册 服务发现 负载均 ...

随机推荐

  1. npm 安装 sass 引用

    1.npm install node-sass --save-dev 2.npm install sass-loader --save-dev npm i less-loader  --save-de ...

  2. [USACO10OCT] Lake Counting S

    传送锚点:https://www.luogu.com.cn/problem/P1596 由于近期的降雨,雨水汇集在农民约翰的田地不同的地方.我们用一个 \(N\times M(1\leq N\leq ...

  3. CentOS搭建Jellyfin影音服务器

    一. 安装Jellyfin 之前介绍过Docker安装jellyfin,但Docker安装方式存在一些限制,于是一起学习一下用RPM包在CentOS 7下安装方法. 先安装需要的依赖: yum ins ...

  4. golang 怎么获取kubernetes deployments的状态?

    如果我们需要把k8s的信息展示为一个友好的web页面.那么deployment 的信息基本上是非常重要的(大部分的服务都是使用deployment部署). 从yaml 中我们能获取到很多关于deplo ...

  5. 鸿蒙HarmonyOS实战-Stage模型(线程模型)

    前言 线程是计算机中的一种执行单元,是操作系统进行调度的最小单位.它是进程中的实际运行单位,每个进程可以包含多个线程.线程可以理解为进程中的一个执行流,它独立运行,拥有独立的栈和寄存器,但共享进程的资 ...

  6. @synchronized(self) 加锁引起的Crash

    一.最近米家App进入前台的时候上报上来一个Crash {"app_name":"MiHome","timestamp":"201 ...

  7. gRPC入门学习之旅(九)

    gRPC入门学习之旅目录 gRPC入门学习之旅(一) gRPC入门学习之旅(二) gRPC入门学习之旅(三) gRPC入门学习之旅(四) gRPC入门学习之旅(七)   3.10.客户端编译生成GRP ...

  8. HMI-Board上手指南

    介绍 HMI-Board为 RT-Thread 联合瑞萨推出的高性价比图形评估套件,取代传统的 HMI+主控板硬件,一套硬件即可实现 HMI+IoT+控制的全套能力.依托于瑞萨高性能芯片 RA6M3 ...

  9. 8.9考试总结(NOIP模拟34)[Merchant·Equation·Rectangle]

    一个人有表里两面,你能看到的,仅仅是其中一面而已. 今日已成往昔,明日即将到来,为此理所当然之事,感到无比痛心. T1 Merchant 解题思路 我和正解也许就是差了一个函数(我格局小了..) nt ...

  10. OOP课第一阶段总结

    前三次OOP作业总结Blog 前言 作为第一次3+1的总结,这次题目集的难度逐渐升高,题量.阅读量和测试点的数量变化都很大,所以对我们的编程和理解能力提出了更高的要求.要求我们能够熟练的掌握正则表达式 ...