Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
NHibernate:通过基于用户文化交换列进行本地化_Nhibernate_Fluent Nhibernate_Localization_Nhibernate Mapping - Fatal编程技术网

NHibernate:通过基于用户文化交换列进行本地化

NHibernate:通过基于用户文化交换列进行本地化,nhibernate,fluent-nhibernate,localization,nhibernate-mapping,Nhibernate,Fluent Nhibernate,Localization,Nhibernate Mapping,我读过关于NHibernate本地化的文章,但似乎没有什么东西非常适合这种情况。我们的数据库使用以下模式存储本地化信息: TABLE NAME: PRODUCT COLUMNS: ID PRODUCT_CODE PRODUCT_NAME DESCRIPTION1 DESCRIPTION2 DESCRIPTION3 字段DESCRIPTION1、DESCRIPTION2和DESCRIPTION3包含产品的本地化描述。始终只有三个本地化字符串,并且数字始终表示相同的区域性(例如,3是英语)。在其

我读过关于NHibernate本地化的文章,但似乎没有什么东西非常适合这种情况。我们的数据库使用以下模式存储本地化信息:

TABLE NAME: PRODUCT
COLUMNS: 
ID
PRODUCT_CODE
PRODUCT_NAME
DESCRIPTION1
DESCRIPTION2
DESCRIPTION3
字段DESCRIPTION1、DESCRIPTION2和DESCRIPTION3包含产品的本地化描述。始终只有三个本地化字符串,并且数字始终表示相同的区域性(例如,3是英语)。在其他一些表中,我们有像NAME1、NAME2和NAME3这样的列

我希望使用(Fluent)NHibernate映射到这些列,这样模型类将只包含一个名为“Description”的属性,并且它将包含根据当前线程的区域性从正确字段获得的值。NHibernate似乎有多个扩展点,但哪一个是最好的

将字符串属性动态映射到正确的列?

在我的梦境中,我会将描述字段作为字符串

public class Product
{
    /* ... */

    public virtual string Description { get; set; }
}
在类映射中,我会告诉Fluent NHibernate在运行时计算正确的列名:

public class ProductMap : ClassMap<Product>
{
    public ProductMap()
    {
        /* ... */

        MapAsLocalized(x => x.Description);
    }
}
然后获取本地化值,例如:

public class Product
{
    /* ... */

    public virtual LocalizedString Description { get; set; }
}
        // Product prod;
        // Get product from db

        Console.WriteLine(prod.Description.Value);
在LocalizedString示例中,开发人员仍然可以创建映射,而无需创建到每个描述列的映射:

public class ProductMap : ClassMap<Product>
{
    public ProductMap()
    {
        /* ... */

        Map(x => x.Description);
    }
}
公共类ProductMap:ClassMap
{
公共产品地图()
{
/* ... */
映射(x=>x.Description);
}
}
当使用此映射执行查询时,它将返回LocalizedString(内部是某种类型的集合)中的DESCRIPTION1、DESCRIPTION2和DESCRIPTION3的值


关于如何实施解决方案1或解决方案2有何建议?或者两者都可以?

而NHibernate确实提供了在运行时修改映射的工具。每次需要执行查询时,NHibernate都要重建会话工厂,这将严重影响性能。我建议使用你的第二个想法。您甚至不需要自定义IUserType。可以将其映射为组件

Component(x => x.Description, c => 
     {
          c.Map(d => d.Description1);
          ...
     });

或者,您可以将这些描述映射到产品类中的支持字段,并提供公共描述属性,该属性在运行时选择适当的字段。

您可以使用用户类型

public class LocalizationUserType : ImmutableUserType
{
    public override object NullSafeGet(IDataReader rs, string[] names, object owner)
    {
        switch(Languageprovider.GetLanguage())
        {
             case language1:
                  return NHibernateUtil.String.NullSafeGet(cmd, value, index);
             case language2:
                  return NHibernateUtil.String.NullSafeGet(cmd, value, index + 1);
             ...
        }
        return null;
    }

    public override void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        switch(Languageprovider.GetLanguage())
        {
             case language1:
                  NHibernateUtil.String.NullSafeSet(cmd, value, index);
                  break;
             case language2:
                  NHibernateUtil.String.NullSafeSet(cmd, value, index + 1);
                  break;
             ...
        }
    }

    public override Type ReturnedType
    {
        get { return typeof(String); }
    }

    public override SqlType[] SqlTypes
    {
        get { return new[]
        {
            SqlTypeFactory.GetString(1000),
            SqlTypeFactory.GetString(1000),
            SqlTypeFactory.GetString(1000),
        }; }
    }
}
ImmutableUserType是一个基类,实现了一些IUserType方法。如果你愿意,我可以发送实现

使用方法:

public class ProductMap : ClassMap<Product>
{
     ProductMap
     {
         ...
         Map(p => p.Name)
             .Columns.Add("name1", "name2", "name3")
             .CustomType<LocalizationUserType>();

         ...
         Map(p => p.Description)
             .Columns.Add("desc1", "desc2", "desc3")
             .CustomType<LocalizationUserType>();
公共类ProductMap:ClassMap
{
产品地图
{
...
映射(p=>p.Name)
.列。添加(“名称1”、“名称2”、“名称3”)
.CustomType();
...
映射(p=>p.Description)
.列。添加(“说明1”、“说明2”、“说明3”)
.CustomType();

我能给出的唯一建议(无用)是修复DB模式。您如何在当前设计中添加另一种语言?不幸的是,我们的数据库是一个遗留的数据库,可以追溯到近20年前。您是否大量使用投影?这将影响解决方案。