首先使用 EF 代码本地化实体的最佳实践 [英] Best Practices to localize entities with EF Code first
问题描述
我正在使用 EF Code First 开发域模型来持久化数据.我必须添加对多语言的支持,并且我不想用位置概念污染域模型.
I am developing a domain model using EF Code First to persist the data. I have to add support for multilanguage and I would like not to contaminate the domain model with location concepts.
我喜欢在数据库中存在一个带有标题和语言字段的 ProductTranslate 表,但在我的域中,标题属于产品实体.
I like that in database exists a ProductTranslate table with title and Language fields but in my domain title belongs to the Product entity.
有人知道怎么弄这个吗?
Someone knows how to get this?
推荐答案
这是我使用的,并且首先与代码配合使用.
Here is what I use and works well with code first.
定义一个基本的Translation
类:
using System;
public abstract class Translation<T> where T : Translation<T>, new()
{
public Guid Id { get; set; }
public string CultureName { get; set; }
protected Translation()
{
Id = Guid.NewGuid();
}
}
定义一个TranslationCollection
类:
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
public class TranslationCollection<T> : Collection<T> where T : Translation<T>, new()
{
public T this[CultureInfo culture]
{
get
{
var translation = this.FirstOrDefault(x => x.CultureName == culture.Name);
if (translation == null)
{
translation = new T();
translation.CultureName = culture.Name;
Add(translation);
}
return translation;
}
set
{
var translation = this.FirstOrDefault(x => x.CultureName == culture.Name);
if (translation != null)
{
Remove(translation);
}
value.CultureName = culture.Name;
Add(value);
}
}
public T this[string culture]
{
get
{
var translation = this.FirstOrDefault(x => x.CultureName == culture);
if (translation == null)
{
translation = new T();
translation.CultureName = culture;
Add(translation);
}
return translation;
}
set
{
var translation = this.FirstOrDefault(x => x.CultureName == culture);
if (translation != null)
{
Remove(translation);
}
value.CultureName = culture;
Add(value);
}
}
public bool HasCulture(string culture)
{
return this.Any(x => x.CultureName == culture);
}
public bool HasCulture(CultureInfo culture)
{
return this.Any(x => x.CultureName == culture.Name);
}
}
然后您可以在实体中使用这些类,例如:
You can then use those classes in your entities, e.g.:
using System;
using System.Globalization;
public class HelpTopic
{
public Guid Id { get; set; }
public string Name { get; set; }
public TranslationCollection<HelpTopicTranslation> Translations { get; set; }
public string Content
{
get { return Translations[CultureInfo.CurrentCulture].Content; }
set { Translations[CultureInfo.CurrentCulture].Content = value; }
}
public HelpTopic()
{
Id = Guid.NewGuid();
Translations = new TranslationCollection<HelpTopicTranslation>();
}
}
将HelpTopicTranslation
定义为:
using System;
public class HelpTopicTranslation : Translation<HelpTopicTranslation>
{
public Guid Id { get; set; }
public Guid HelpTopicId { get; set; }
public string Content { get; set; }
public HelpTopicTranslation()
{
Id = Guid.NewGuid();
}
}
现在,对于代码优先的特定方面,使用以下配置:
Now, for the code first specific side of things, use the following configuration:
using System.Data.Entity.ModelConfiguration;
using Model;
internal class HelpTopicConfiguration : EntityTypeConfiguration<HelpTopic>
{
public HelpTopicConfiguration()
{
Ignore(x => x.Content); // Ignore HelpTopic.Content since it's a 'computed' field.
HasMany(x => x.Translations).WithRequired().HasForeignKey(x => x.HelpTopicId);
}
}
并将其添加到您的上下文配置中:
And add it to your context configurations:
public class TestContext : DbContext
{
public DbSet<HelpTopic> HelpTopics { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new HelpTopicConfiguration());
}
}
所有这些都完成后,会生成以下迁移:
When all of this is done, the following migration is generated:
using System.Data.Entity.Migrations;
public partial class AddHelpTopicTable : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.HelpTopics",
c => new
{
Id = c.Guid(false),
Name = c.String(),
})
.PrimaryKey(t => t.Id);
CreateTable(
"dbo.HelpTopicTranslations",
c => new
{
Id = c.Guid(false),
HelpTopicId = c.Guid(false),
Content = c.String(),
CultureName = c.String(),
})
.PrimaryKey(t => t.Id)
.ForeignKey("dbo.HelpTopics", t => t.HelpTopicId, true)
.Index(t => t.HelpTopicId);
}
public override void Down()
{
DropForeignKey("dbo.HelpTopicTranslations", "HelpTopicId", "dbo.HelpTopics");
DropIndex("dbo.HelpTopicTranslations", new[] { "HelpTopicId" });
DropTable("dbo.HelpTopicTranslations");
DropTable("dbo.HelpTopics");
}
}
欢迎任何意见和/或改进...
Any comments and/or improvements are welcome...
这篇关于首先使用 EF 代码本地化实体的最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!