为多语言数据库提供流畅的API支持

本文关键字:API 支持 语言 数据库 | 更新日期: 2023-09-27 18:01:13

我在一个多语言网站上工作(MVC 5,EF 6.1(。为了支持某些字段的多种语言,我将表分为两部分。一个用于与语言无关的数据,另一个用于语言相关的数据。

例如,我的产品表是(简化的(:

Product
 - Id int
 - Price float
ProductLang
 - ProductId int
 - LanguageId int
 - Name nvarchar
 - Desc nvarchar

因此,对于上面的结构,我创建了2个实体类和一个ModelBuilder映射:

modelBuilder.Entity<ProductLang>().HasKey(t => new { t.ProductId,  t.LanguageId });

一切都很好,EF用上面的字段创建了我的数据库。在这一点上,我有点困惑。CRUD操作的最佳方式是什么?

如何查询数据?我只是在下面写了这个代码,但我不知道这是否是最好的方法:

var test = context.Product.Select(t => new 
{ 
  Id         = t.Id, 
  Price      = t.Price, 
  Translated = t.ProductLang.Where(x => x.LanguageId == 1).FirstOrDefault(),
}).FirstOrDefault();

通过这种技术,我可以非常简单地获得值:

Int32  id       = test.Id;
Double price    = test.Price;
String name     = test.Translated.Name;
String descr    = test.Translated.Descr;

如何创建新记录?我的测试代码是:

Product product1 = new Product();
product1.Price = 3.99;
context.Product.Add(product1);
ProductLang translate1 = new ProductLang();
translate1.Language = language1;
translate1.Product = product1;
translate1.Name = "My First Product";
context.ProductLang.Add(translate1);
context.SaveChanges();

上面的代码运行良好,但我不确定这是否是处理多语言(拆分表(数据库结构的最佳方式。EF或FluentAPI中是否有任何基础设施可以更简单、更好地处理这一问题?有什么模式或惯例吗?如果我有多个已翻译的表,我应该使用抽象基类来处理这些操作吗?出于任何原因,我应该在这里使用泛型吗?

为多语言数据库提供流畅的API支持

考虑添加一个额外的抽象层,以保护网站的其余部分不受用于表示本地化信息的物理结构的影响。

例如,您可以创建一个平面"产品"实体,该实体将具有相同的结构,无论它是否本地化。在查询过程中,将两个表(独立于语言并本地化(映射到该数据结构中:

var test = 
(
  from t in context.ProductLang
  where t.ProductId == 5 && t.Language = "en"
  select new Website.Model.Product
  {
    Id = t.Product.Id,
    Price = t.Product.Price,  // Language independent
    Name = t.Name             // Language dependent
  }
).SingleOrDefault();

如果你把代码包装在一个函数或接口中,你的调用代码可以很容易地检索信息,而不必担心它是如何表示的:

var test = DataService.GetProduct(5, "en");

更新也可以以同样的方式进行。诀窍是更新会变得有点困难,因为你不一定知道是否要创建独立于语言的记录。这使得更新代码更加复杂——为了实现完全的线程安全,您必须使用带锁定的事务。如果本地化内容的更新不频繁,您可以在EF逻辑中使用"if语句"。