多语言实体

介绍

ASP.NET Boilerplate 为多语言实体定义了两个基本接口,以便为转换实体提供标准模型。

IMultiLingualEntity

IMultiLingualEntity<TTranslation>接口用于标记转换的多语言实体。标有IMultiLingualEntity<TTranslation>接口的实体必须定义与语言无关的信息。带有IMultiLingualEntity<TTranslation> 标记的实体包含转换集合,其中包含与语言相关的信息。

一个多语言实体样本是;

public class Product : Entity, IMultiLingualEntity<ProductTranslation>
{
    public decimal Price { get; set; }

    public ICollection<ProductTranslation> Translations { get; set; }
}

IEntityTranslation

IEntityTranslation 接口用于标记多语言实体的转换。标有 IEntityTranslation 接口的实体必须定义与语言相关的信息。标有 IEntityTranslation 的实体包含语言字段,其中包含转换的语言代码和对多语言实体的引用。

一个多语言实体样本将是;

public class ProductTranslation : Entity, IEntityTranslation<Product>
{
    public string Name { get; set; }

    public Product Core { get; set; }

    public int CoreId { get; set; }

    public string Language { get; set; }
}

CreateMultiLingualMap

在用户界面上列出多语言实体时,大多数情况下,只有一种多语言实体的转换,在用户的当前语言中,只有一个多语言实体的转换将被展示给用户。 

为此,ABP定义了 CreateMultiLingualMap 扩展方法,被用于 AutoMapper 将多语言实体及其中一个实体映射到适当的 Dto 类

通过使用 CreateMultiLingualMap 扩展方法,只有来自多语言实体的 Translations 集合的一条记录将映射到目标 Dto 类。此扩展方法首先查找具有所选 UI 语言的转换。如果没有使用所选 UI 语言的转换,则扩展方法将搜索默认语言设置(请参阅 设置 - 管理)并使用默认语言进行转换。如果扩展方法无法在当前 UI 语言或默认语言中找到任何翻译,则它使用现有转换之一。

以上样本产品实体的样本 Dto 类将是;

public class ProductListDto
{
    // Mapped from Product.Price
    public decimal Price { get; set; }

    // Mapped from ProductTranslation.Name
    public string Name { get; set; }
}

它的映射配置是;

Configuration.Modules.AbpAutoMapper().Configurators.Add(configuration =>
{
    CustomDtoMapper.CreateMappings(configuration, new MultiLingualMapContext(
        IocManager.Resolve<ISettingManager>()
    ));
});

internal static class CustomDtoMapper
{
    public static void CreateMappings(IMapperConfigurationExpression configuration, MultiLingualMapContext context)
    {
        configuration.CreateMultiLingualMap<Product, ProductTranslation, ProductListDto>(context);
    }
}

在将多语言实体映射到 Dto 类时,需要 SettingManager 查找默认语言设置。

在某些情况下,例如在 UI 上编辑多语言实体,Dto 类中可能需要所有转换。在这种情况下,Dto 类可以如下定义,并且可以使用 Object-To-Object-Mapping

[AutoMap(typeof(Product))]
public class ProductDto
{
    public decimal Price { get; set; }

    public List<ProductTranslationDto> Translations {get; set;}
}



[AutoMap(typeof(ProductTranslation))]
public class ProductTranslationDto
{
    public string Name { get; set; }
}

Crud 操作

创建具有转换的多语言实体

像下面这样的 Dto 类可以用于创建转换的多语言实体。

[AutoMap(typeof(Product))]
public class ProductDto
{
    public decimal Price { get; set; }

    public ICollection<ProductTranslationDto> Translations { get; set; }
}

在定义了这样的 Dto 类之后,我们可以在我们的应用程序服务中使用它来创建一个多语言实体。

public class ProductAppService : ApplicationService, IProductAppService
{
    private readonly IRepository<Product> _productRepository;

    public ProductAppService(IRepository<Product> productRepository)
    {
        _productRepository = productRepository;
    }

    public async Task CreateProduct(ProductDto input)
    {
        var product = ObjectMapper.Map<Product>(input);
        await _productRepository.InsertAsync(product);
    }
}

使用转换更新多语言实体

我们可以使用类似的 Dto 类来更新我们的多语言实体。用于更新操作的示例应用服务方法可以如下定义;

public async Task UpdateProduct(ProductDto input)
{
    var product = await _productRepository.GetAllIncluding(p => p.Translations)
        .FirstOrDefaultAsync(p => p.Id == input.Id);

    product.Translations.Clear();

    ObjectMapper.Map(input, product);
}
EntityFramework 6.x 的注释

对于 EntityFramework 6.x,必须手动从数据库中删除所有转换,因为 Entity Framework 6.x 不会删除相关数据。相反,EntityFramework 6.x 尝试将每个 Translation 实体的 CoreId 设置为 null,这将会以失败告终。因此,可以使用类似下面的示例代码来删除EntityFramework 6.x 的多语言实体的翻译。

foreach (var translation in product.Translations.ToList())
{
    await _productTranslationRepository.DeleteAsync(translation);
    product.Translations.Remove(translation);
}

nidie.com.cn - 用心与你沟通