I want my entity's text properties being saved in several languages. For this I just want to store a FK to the TextContent table (which basically contains only a key) and a separate Translation table which contains a row for each translation.
Here is my database model
And my corresponding entities
public sealed class Translation : IEquatable<Translation>
{
public static bool operator ==(Translation left, Translation right) => Equals(left, right);
public static bool operator !=(Translation left, Translation right) => !Equals(left, right);
// ORM-only constructor
private Translation() { }
public Translation(int languageId, string text)
{
_language = languageId;
_text = text;
}
public bool Equals(Translation other) ...
public override bool Equals(object obj) ...
public override int GetHashCode() ...
public int LanguageId => _language;
public string Text => _text;
private readonly int _languageId;
private readonly string _text;
}
public class TextContent
{
// ORM-only constructor
protected TextContent() { }
public TextContent(int Id, List<Translation> translations)
{
_id = Id;
_originalLanguage = translations.First().LanguageId;
_originalText = translations.First().Text;
_translations = translations;
}
public virtual int Id => _id;
public virtual int OriginalLanguageId => _originalLanguage;
public virtual string OriginalText => _originalText;
public virtual IList<Translation> Translations => _translations;
private readonly int _id;
private readonly int _originalLanguageId;
private readonly string _originalText;
private readonly IList<Translation> _translations;
}
public partial class Product
{
// ORM-only constructor
protected Product() { }
public Product(int Id, TextContent name, TextContent description)
{
_id = Id;
_nameId = name.Id;
_name = name;
_descriptionId = description.Id;
_description = description;
}
public virtual int Id => _id;
public virtual TextContent Name => _name;
public virtual TextContent Description => _description;
private int _id;
private int _nameId;
private TextContent _name;
private int _descriptionId;
private TextContent _description;
}
The mappings I tried
public class TextContentMapping : ClassMapping<TextContent>
{
public TextContentMapping()
{
Table("TextContent");
Id(content => content.Id);
Property(content => content.OriginalLanguage);
Property(content => content.OriginalText);
Bag(
content => content.Translations,
mapper =>
{
mapper.Table(nameof(Translation));
mapper.Cascade(Cascade.All);
mapper.Key(
keyMapper =>
{
keyMapper.Column(columnMapper => columnMapper.Name("TextContentId"));
keyMapper.NotNullable(true);
});
},
relation => relation.Component(
mapper =>
{
mapper.Property(translation => translation.LanguageId);
mapper.Property(translation => translation.Text);
}));
}
}
public class ProductMapping : ClassMapping<Product>
{
public ProductMapping()
{
Table(nameof(Product));
Id(product=> product.Id, mapper => mapper.Access(Accessor.Field));
Property(
"_nameId",
mapper =>
{
mapper.Column("NameId");
mapper.Access(Accessor.Field);
mapper.NotNullable(true);
});
Property(
"_descriptionId",
mapper =>
{
mapper.Column("DescriptionId");
mapper.Access(Accessor.Field);
mapper.NotNullable(true);
});
OneToOne(
product => product.Name,
mapper =>
{
mapper.Constrained(true);
mapper.Cascade(Cascade.All);
mapper.Access(Accessor.Field);
mapper.Class(typeof(TextContent));
});
OneToOne(
product => product.Description,
mapper =>
{
mapper.Constrained(true);
mapper.Cascade(Cascade.All);
mapper.Access(Accessor.Field);
mapper.Class(typeof(TextContent));
});
}
}
As you may guess the insert works but the select doesn't as my current mapping don't provide a link between _nameId
and TextContent Name
entity ?
Is there a way to do it ? If not what would be a better mappings and domain entities that correspond to my database model?