基于EF Core存储的国际化服务

ef,core · 浏览次数 : 23

小编点评

前言:.NET官方提供了一个用于管理国际化资源的扩展包Microsoft.Extensions.Localization,ASP.NET Core也使用这个来实现国际化功能。但是这个包的翻译数据是使用resx资源文件来管理的,这就意味着无法动态管理。虽然官方有在文档中提供了一些第三方管理方案,但是都不太方便。其中一个是基于Json文件的,虽然可以动态管理,但是正确的Key值有时很难猜对,特别是对于嵌套类和泛型类之类名字比较特殊的。另外两个基于EF Core的一个只是个demo;另一个已多年未更新,且上下文生命周期和并发管理有缺陷(这个库还是我提交pr才支持的 .NET 5)。最近项目有用到国际化功能,只好重新写一个。新书宣传有关新书的更多介绍欢迎查看《C#与.NET6 开发从入门到实践》上市,作者亲自来打广告了! 相关旧文:Asp.Net Core 混合全球化与本地化支持正文 这个扩展包代码不多也不算复杂,主要结构参考官方内置实现。对于 .NET 5以上支持上下文工厂的版本使用上下文工厂,而对于旧版本则创建内部作用域获取私有上下文,以此彻底避免并发问题。作用域和上下文都是需要查询时临时获取和使用,查询完数据立即销毁避免内存泄漏。如果使用池化上下文工厂性能会更好。对代码感兴趣的朋友可以移步Github。 这里直接介绍一下基本用法。这个库分为三个包:抽象包定义了所需接口,实体模型包定义基本实体类型,功能包定义了服务接口的实现类和用于注册服务的扩展方法。方便为分离项目的解决方案按需引用,减少无关类型的污染。以在ASP.NET Core中使用为例: 实体模型和上下文 ```csharp public class YourLocalizationRecord : LocalizationRecord { public int YourProperty { get; set; } } public class YourDbContext : DbContext { protected override void OnModelCreating(ModelBuilder modelBuilder) { // 使用默认类型。 modelBuilder.UseLocalizationRecord(); // 使用自定义类型,需要继承LocalizationRecord。 modelBuilder.UseLocalizationRecord(b => { b.Property(r => r.ResourceCulture).HasMaxLength(32); b.ToTable($"YourLocalizationRecords"); }); } } ``` 服务注册 // 对于 .NET 5 以上请使用上下文工厂。 services.AddDbContextFactory(options => options.UseSqlite("Localization.db")); // 或者池化工厂也是一样的,而且更好。 services.AddPooledDbContextFactory(options => options.UseSqlite("Localization.db")); // 注册一个自定义工厂服务 services.AddScoped(sp => sp.GetRequiredService>().CreateDbContext()); // 对于 .NETStandard 2.0 或 2.1 请使用上下文。 services.AddDbContext(options => options.UseSqlite("Localization.db")); // 注册使用默认实体类型的服务。 services.AddEntityFrameworkCoreLocalization(); // 注册使用自定义实体类型的服务。 services.AddEntityFrameworkCoreLocalization(); 其他的和官方文档用法完全一致,如果需要清除缓存使资源能在下次读取时更新,可以使用服务IDynamicResourceStringLocalizerFactory。这个服务继承自内置服务,获取的IStringLocalizerFactory服务实际上也是IDynamicResourceStringLocalizerFactory的实现。 既然已经有上下文了,想怎么读写数据应该不必多言了吧。实体类的属性LocalizedContent就是翻译后的文本。如果使用自动创建记录,只需要查找所有这个属性为null的记录并翻译保存,最后清除缓存即可。 结语:为了实现对 .NET Standard 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。

正文

前言

.NET 官方有一个用来管理国际化资源的扩展包Microsoft.Extensions.Localization,ASP.NET Core也用这个来实现国际化功能。但是这个包的翻译数据是使用resx资源文件来管理的,这就意味着无法动态管理。虽然官方有在文档中提供了一些第三方管理方案,但是都不太方便。其中一个是基于Json文件的,虽然可以动态管理,但是正确的Key值有时很难猜对,特别是对于嵌套类和泛型类之类名字比较特殊的。另外两个基于EF Core的一个只是个demo;另一个已多年未更新,且上下文生命周期和并发管理有缺陷(这个库还是我提交pr才支持的 .NET 5)。最近项目有用到国际化功能,只好重新写一个。

新书宣传

有关新书的更多介绍欢迎查看《C#与.NET6 开发从入门到实践》上市,作者亲自来打广告了!
image

相关旧文

Asp.Net Core 混合全球化与本地化支持

正文

这个扩展包代码不多也不算复杂,主要结构参考官方内置实现。对于 .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的记录并翻译保存,最后清除缓存即可。

image

结语

为了实现对 .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
image

欢迎读者和广大朋友一起交流,如发现本书错误也欢迎通过博客园、QQ群等方式告知笔者。

本文地址:https://www.cnblogs.com/coredx/p/18294729.html

与基于EF Core存储的国际化服务相似的内容:

基于EF Core存储的国际化服务

前言 .NET 官方有一个用来管理国际化资源的扩展包Microsoft.Extensions.Localization,ASP.NET Core也用这个来实现国际化功能。但是这个包的翻译数据是使用resx资源文件来管理的,这就意味着无法动态管理。虽然官方有在文档中提供了一些第三方管理方案,但是都不太

基于EF Core存储的Serilog持久化服务

前言 Serilog是 .NET 上的一个原生结构化高性能日志库,这个库能实现一些比内置库更高度的定制。日志持久化是其中一个非常重要的功能,生产环境通常很难挂接调试器或者某些bug的触发条件很奇怪。为了在脱离调试环境的情况下尽可能保留更多线索来辅助解决生产问题,持久化的日志就显得很重要了。目前Ser

EF Core + MySQL 基本增删改查

# 前言 基于EF Core + MySQL的基本增删改查,示例是基于[.NET6 + EF Core + MySQL 创建实体和数据库、EFCore 数据迁移](https://www.cnblogs.com/lym003/p/17411699.html)项目基础上的内容增加。同时也是对[基于Ca

使用EF 连接 数据库 SQLserver、MySql 实现 CodeFirst

1.新建项目,下载Nuget安装包 创建项目需要注意几点,如果是基于 .net framework 的项目 需要选择 相应版本的 EF, 如果是跨平台则选择EF Core版本。 我这里选择的是 .net framework 版本。红框里面是 实现EF Code First 需要的包。 对应的版本:

EF Core从TPH迁移到TPT

Intro EF Core支持多种方式处理具有继承关系的表,现在支持TPH、TPC(EF Core 7)、TPT,具体的实现方式可以参考官方文档和这篇文章。 大致总结一下不同的方式的区别: TPH:所有的类型都放在一张表中,使用discriminator字段用以区别不同的类型 TPT:不同的子类型有

造轮子之ORM集成

Dotnet的ORM千千万,还是喜欢用EF CORE 前面一些基础完成的差不多了,接下来可以集成数据库了,官方出品的ORM还是比较香。所以接下来就是来集成EF CORE。 安装包 首先我们需要安装一下EF CORE的NUGET包,有如下几个: Microsoft.EntityFrameworkCor

Ubuntu22.04 安装单机版kubernetes

# 前言 上期讲到要实现.net 6框架下的EF Core操作数据库基本增删改查,没有及时兑现。没有兑现的原因就是因为安装kubernetes。安装kubernetes的过程是灾难性的,也是十分顺利的。灾难性是因为在安装kubernetes过程中误操作,在/etc下执行了一个重置的命令导致我的工作站

外键拆分手记

我习惯性使用OData,它的$expand与层级查询非常好用,这个功能非常依赖于数据库的导航属性,也就是外键结构。最近想着把一个单体的系统拆分为多个小系统,首先需要处理外键依赖的问题。 多个服务各自有各自的数据库,数据库层面并不互通,也就无法使用外键约束。 我使用EF Core来描述数据库的结构,有

WTM的项目中EFCore如何适配人大金仓数据库

一、WTM是什么 WalkingTec.Mvvm框架(简称WTM)最早开发与2013年,基于Asp.net MVC3 和 最早的Entity Framework, 当初主要是为了解决公司内部开发效率低,代码风格不统一的问题。2017年9月,将代码移植到了.Net Core上,并进行了深度优化和重构,

基于 Three.js 的 3D 模型加载优化

作为一个3D的项目,从用户打开页面到最终模型的渲染加载的时间也会比普通的H5项目要更长一些,从而造成大量的用户流失。为了提升首屏加载的转化率,需要尽可能的降低loading的时间。这里就分享一些我们在模型加载优化方面的心得。