0

我在一个多语言网站(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 中是否有任何基础设施可以更简单、更好地处理这个问题?有什么模式或约定吗?如果我有多个翻译表,我应该使用抽象基类来处理这些操作吗?我应该出于任何原因在这里使用泛型吗?

4

1 回答 1

0

考虑添加一个额外的抽象层,将网站的其余部分与用于表示本地化信息的物理结构隔离开来。

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

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 语句”。

于 2014-05-26T22:06:54.693 回答