问题描述
对不起,一个漫长的问题。但是,值得给予所有的细节,所以请与我一直到最后。我正在对遗留的数据库,我没有太多的控制。我希望能够将一个类映射到多个数据库表。这里是我的表看看
Lookup
+ -------- + -------------- + ------------ +
|列| DataType |属性|
+ -------- + -------------- + ------------ +
| Id | INT | PK |
|代码| NVARCHAR(50)| |
+ -------- + -------------- + ------------ +
$ c
$ b $文化+ -------------- + -------------- + ---------- - +
|列| DataType |属性|
+ -------------- + -------------- + ------------ +
| Id | INT | PK |
| Culture_Code | NVARCHAR(10)| |
+ -------------- + -------------- + ------------ +
Lookup_t9n
+ ---------------- + --------------- + - -------------------- +
|列| DataType |属性|
+ ---------------- + --------------- + ------------ --------- +
| Id | INT | PK |
| Culture_Id | INT | FK到文化表|
| Localised_Text | NVARCHAR(MAX)| |
+ ---------------- + --------------- + ------------ --------- +
正如您所看到的,我有一个查找表所有查找都被存储。查找的显示文本已本地化并存储在单独的表中。该表具有文化表的外键以指示本地化文本存在的文化。
我的类看起来像这样
public class Lookup {
public virtual int Id {get; set;}
public virtual string Code {get; set;}
public virtual string DisplayText {get; set;}
}
我的FNH映射类看起来像这样
public class LookupMappings:ClassMap< Lookup> {
public LookupMappings()
{
Table(Lookup);
Id(x => x.Id).Column(Id);
Map(x => x.Code).Column(Code);
Join(Lookup_t9n,join => {
join.Map(x => x.DisplayText).Column(Localised_Text); //注意这个地方,我的问题在这里
})
}
}
上面的映射,在加入部分我想提供一些where子句像 WHERE Lookup_t9n.Culture_Id = Culture.Culture_Id和Culture.Culture_Code = System.Threading。 Thread.CurrentUICulture.CultureCode 。
我知道这不是一个有效的SQL,但表达了我希望的意图。有没有人有任何这样的事情的经验。
我可以添加一个映射层,在这里我可以使用与数据库表一一对应的类,然后编写纯c#将这些类映射回我的 Lookup class。我宁愿这样做,作为一个临时解决方案。我想知道是否可以删除那个智能NH使用映射层。
解决方案我没有简单的答案, EM> CallThis() 。我想根据我们如何使用类似的东西给你提供建议。该解决方案基于标准映射,将其复杂性隐藏在C#实体中。这只是一个解决方案的草案,所以我会跳过中间的文化表,并期望在 Lookup_t9n 我们只存储文化名称( en , cs ...)
让我们有这个课程
public class Lookup {
public virtual int Id {get; set;}
public virtual string Code {get; set;}
//为简单起见,跳过空检查
public virtual DisplayText {get {return Localizations.First()。LocalizedText; }}
公共虚拟IList<本地化>本地化{get; set;}
}
public class Localization {//映射到Lookup_t9n
public virtual string CultureName {get; set;}
公共虚拟字符串LocalizedText {get;设置;}
}
有了这个,我们可以映射 em> 本地化作为 HasMany 。它甚至可以被映射为一个组件(请参阅)
现在,我们需要的是引入一个过滤器。 。基本文档:。
$ b $ p简化映射
过滤器:
public class CulturFilter:FilterDefinition
{
public CulturFilter()
{
WithName(CulturFilter)
.AddParameter(culture,NHibernate.NHibernateUtil.String);
$ / code>收藏:
<$ (x => x.Localization)
.KeyColumn(Id)
...
.ApplyFilter< CulturFilter>(CultureName =:culture))
.Cascade.AllDeleteOrphan();
最后,我们必须介绍一些AOP过滤器,IInterceptor ...需要)并调整 ISession
session
.EnableFilter (CulturFilter)
.SetParameter(culture
,System.Globalization.CultureInfo.CurrentCulture.TwoLetterISOLanguageName);
现在我们有 Localized string based on 当前文化,同时使用本地化值的标准映射作为集合。
Sorry for a lengthy question. But it is worth giving all the details so please bear with me through to the end.
I'm working against a legacy database over which I do not have much control. I want to be able to map a class to multiple database tables. Here is how my tables look
Lookup
+--------+--------------+------------+ | Column | DataType | Attributes | +--------+--------------+------------+ | Id | INT | PK | | Code | NVARCHAR(50) | | +--------+--------------+------------+
Culture
+--------------+--------------+------------+ | Column | DataType | Attributes | +--------------+--------------+------------+ | Id | INT | PK | | Culture_Code | NVARCHAR(10) | | +--------------+--------------+------------+
Lookup_t9n
+----------------+---------------+---------------------+ | Column | DataType | Attributes | +----------------+---------------+---------------------+ | Id | INT | PK | | Culture_Id | INT | FK to Culture table | | Localised_Text | NVARCHAR(MAX) | | +----------------+---------------+---------------------+
As you can see, I have a lookup table where all lookups are stored. The display text for a lookup is localized and stored in a separate table. This table has a foreign key to culture table to indicate the culture for which the localized text exists.
My class looks like this
public class Lookup { public virtual int Id {get; set;} public virtual string Code {get; set;} public virtual string DisplayText {get; set;} }
And my FNH mapping class looks like this
public class LookupMappings : ClassMap<Lookup> { public LookupMappings() { Table("Lookup"); Id(x => x.Id).Column("Id"); Map(x => x.Code).Column("Code"); Join("Lookup_t9n", join => { join.Map(x => x.DisplayText).Column("Localised_Text"); //Note this place, my problem is here }) } }
In the above mapping, in Join part I want to provide some where clause like WHERE Lookup_t9n.Culture_Id = Culture.Culture_Id AND Culture.Culture_Code = System.Threading.Thread.CurrentUICulture.CultureCode.
I know this is not a valid SQL but conveys the intent I hope. Has anyone have any experience of doing such a thing.
I can add a mapping layer where I can have classes that map one-to-one with database tables and then write plain c# to map those classes back to my Lookup class. I have rather done that as an interim solution. I was wondering if I can remove that mapping layer with some smart NH use.
I do not have simple answer, like CallThis(). I would like to give you suggestion, based on how we are using similar stuff. The solution is base on the standard mapping, hidding its complexity in C# Entities. It is just a draft of the solution so I'll skip the middle Culture table, and will expect that in Lookup_t9n we do store just a culture name (en, cs...)
Let's have this class
public class Lookup { public virtual int Id {get; set;} public virtual string Code {get; set;} // for simplicity skipping null checks public virtual DisplayText { get { return Localizations.First().LocalizedText; } } public virtual IList<Localization> Localizations {get; set;} } public class Localization { // mapped to Lookup_t9n public virtual string CultureName {get; set;} public virtual string LocalizedText {get; set;} }
Having this, we can map the collection of Localizations as HasMany. It could even be mapped as a component (see example of component mapping)
Now, what we do need is to introduce a filter. Example with Fluent. The essential documentation: 18.1. NHibernate filters.
Simplified mapping
filter:
public class CulturFilter : FilterDefinition { public CulturFilter() { WithName("CulturFilter") .AddParameter("culture",NHibernate.NHibernateUtil.String); }
collection:
HasMany(x => x.Localization) .KeyColumn("Id") ... .ApplyFilter<CulturFilter>("CultureName = :culture")) .Cascade.AllDeleteOrphan();
Finally, we have to introduce some AOP filter, IInterceptor... which will be triggered each time (needed) and adjust the ISession
session .EnableFilter("CulturFilter") .SetParameter("culture" ,System.Globalization.CultureInfo.CurrentCulture.TwoLetterISOLanguageName);
And now we have Localized string based on current culture, while using standard mapping of localized values as a collection.
这篇关于FluentNHibernate - 将一个类映射到多个表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!