首先使用 EF 代码本地化实体的最佳实践 [英] Best Practices to localize entities with EF Code first

查看:17
本文介绍了首先使用 EF 代码本地化实体的最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆