考虑以下类(为了集中于核心问题而简化):
public class Question
{
public virtual string QuestionId { get; set; }
public virtual string Text { get; set; }
public virtual string Hint { get; set; }
}
和表格:
Question
- QuestionId ((primary key, identity column and key)
- Code
QuestionTranslation
- QuestionTranslationId (primary key, identity column; not really relevant to the association)
- QuestionId (composite key element 1)
- CultureName (composite key element 2) (sample value: en-US, en-CA, es-ES)
- Text
- Hint
如何映射Question类,以便使用当前线程的文化填充Text和Hint属性。如果线程的文化被更改,我希望Text和Hint属性自动返回适当的值,而不需要重新加载Question实体。
请注意,我只是概述了业务方面的相关类和属性。我对完成所需功能所需的任何新类或属性完全开放。
答案 0 :(得分:2)
替代Firo的答案(是的,我复制了它并对其进行了调整并对此感到不满)。
它使用字典并将翻译映射为复合元素(因此它根本不需要id)
public class Question
{
public virtual string QuestionId { get; set; }
public virtual string Text
{
get
{
var translation = Translations[CultureInfo.CurrentCulture.Name];
if (translation != null) return translation.Text
return null;
}
set
{
GetTranslation(CultureInfo.CurrentCulture.Name).Text = value;
}
}
public virtual string Hint
{
get
{
var translation = Translations[CultureInfo.CurrentCulture.Name];
if (translation != null) return translation.Hint
return null;
}
set
{
GetTranslation(CultureInfo.CurrentCulture.Name).Hint = value;
}
}
private QuestionTranslation GetTranslation(CultureInfo.CurrentCulture.Name)
{
QuestionTranslation translation;
if (!Translations.TryGetValue(CultureInfo.CurrentCulture.Name, out translation))
{
translation = new QuestionTranslation()
Translations[CultureInfo.CurrentCulture.Name] = translation;
}
return translation;
}
protected virtual IDictionary<string, QuestionTranslation> Translations { get; private set; }
}
class QuestionTranslation
{
// no id, culture name
public virtual string Text { get; set; }
public virtual string Hint { get; set; }
}
映射:
<class name="Question">
<id name="QuestionId" column="QuestionId"/>
<map name="Translations" table="QuestionTranslation" lazy="true">
<key column="QuestionId"/>
<index column="CultureName"/>
<composite-element class="QuestionTranslation">
<property name="Text"/>
<property name="Hint"/>
</composite-element>
</bag>
</class>
答案 1 :(得分:1)
编辑以反映更改后的答案:
public class Question
{
public virtual string QuestionId { get; set; }
public virtual string Text
{
get
{
var currentculture = CultureInfo.CurrentCulture.Name;
return Translations
.Where(trans => trans.CultureName == currentculture)
.Select(trans => trans.Text)
.FirstOrDefault();
}
set
{
var currentculture = CultureInfo.CurrentCulture.Name;
var translation = Translations
.Where(trans => trans.CultureName == currentculture)
.FirstOrDefault();
if (translation == null)
{
translation = new QuestionTranslation();
Translations.Add(translation);
}
translation.Text = value;
}
}
public virtual string Hint
{
get
{
var currentculture = CultureInfo.CurrentCulture.Name;
return Translations
.Where(trans => trans.CultureName == currentculture)
.Select(trans => trans.Hint)
.FirstOrDefault();
}
set
{
var currentculture = CultureInfo.CurrentCulture.Name;
var translation = Translations
.Where(trans => trans.CultureName == currentculture)
.FirstOrDefault();
if (translation == null)
{
translation = new QuestionTranslation();
Translations.Add(translation);
}
translation.Hint = value;
}
}
protected virtual ICollection<QuestionTranslation> Translations { get; set; }
}
class QuestionTranslation
{
public virtual int Id { get; protected set; }
public virtual string CultureName { get; set; }
public virtual string Text { get; set; }
public virtual string Hint { get; set; }
}
<class name="Question" xmlns="urn:nhibernate-mapping-2.2">
<id name="QuestionId" column="QuestionId"/>
<bag name="Translations" table="QuestionTranslation" lazy="true">
<key>
<column name="QuestionId"/>
</key>
<one-to-many class="QuestionTranslation"/>
</bag>
</class>
<class name="QuestionTranslation" table="QuestionTranslation" xmlns="urn:nhibernate-mapping-2.2">
<id name="QuestionTranslationId"/>
<many-to-one name="ParentQuestion" column="QuestionId"/>
</class>
如果您有大量翻译,请将ICollection<QuestionTranslation> Translations { get; set; }
更改为IDictionary<string, QuestionTranslation> Translations { get; set; }
并将其映射为<map>
,但通常情况下应该这样做