出于隐私原因,我有一个类,我想以两种不同的方式映射到单个表。让我们说这堂课看起来像这样:
class Person
{
public int ID { get; set; }
public string Name { get; set; }
// ... many other properties omitted ...
}
相应的数据库表如下所示:
create table Person
(
ID int not null,
RealName nvarchar(512) not null,
FakeName nvarchar(512) not null,
-- many other columns omitted
)
我需要的两个映射是:
在这两种情况下,所有其他属性应该映射相同。我强烈不希望重复这些其他属性的映射。
我尝试过几种不同的方法但没有运气。使用< union-subclass> 隔离不同的映射失败,并显示以下错误: DuplicateMappingException:Duplicate table mapping Person 。我可以创建两个不同的数据库视图,并分别映射到它们以避免重复的表映射错误,但这不是优选的。
使用“entity-name”属性来指定映射很有诱惑力,但文档记录很差,似乎有一些主要的缺点:a)它需要重复所有其他映射实体,和b)它与<多对一>不兼容来自引用Person类的其他类的关系。
有没有一种方法可以做到这一点,我错过了?
答案 0 :(得分:0)
您可以使用NHibernate公式属性来匹配名称属性,如下所示
<property name="Name" formula="(SELECT id,(CASE WHEN yourcondition then RealName else FakeName end) as Name FROM Person)"/>
您可以参考的公式 - http://blog.khedan.com/2009/01/eager-loading-from-formula-in.html
答案 1 :(得分:0)
尽管我认为OP已经以某种方式解决了他的问题,但我还是想提出一个使用投影的解决方案。
基本上,在您的数据访问层(DAL)中,您可以选择使用投影列表访问数据的稍微复杂的方法,但取决于所需的FakePerson
或RealPerson
类的实例你的逻辑。
它看起来像这样:
FakePerson alias = null;
var person = _session.QueryOver<Person>()
.SelectList(list => list
.Select(go => go.Id).WithAlias(() => alias.Id)
.Select(go => go.FakeName).WithAlias(() => alias.Name) // <- the trick
.Select(go => go.Other).WithAlias(() => alias.Other)
.TransformUsing(Transformers.AliasToBean<FakePerson>());
您仍会使用Person
和FakeName
两个属性映射您的RealName
类,但要将它们protected
并从FakePerson
和RealPerson
派生出来拥有公共Name
财产的人。
我意识到你现在仍然需要两次列出所有属性,它刚刚从映射转移到DAL。好吧,也许这可以帮助那些人,无论如何。