2012-02-23 125 views
2

我有一个类,我想以两种不同的方式映射到单个表,为了隐私的原因。比方说,类看起来是这样的:NHibernate:多个映射到单个表

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 
) 

两个映射我需要的是:

  • 名称属性真实姓名
  • 名称属性别名真实

所有其他属性都应该被映射在这两种情况下是相同的。我强烈希望不必重复这些其他属性的映射。

我尝试了几种不同的方法,没有运气。使用<联合子类>来隔离不同映射失败并出现此错误:DuplicateMappingException:重复表映射人员。我可以创建两个不同的数据库视图,并分别映射它们以避免重复的表映射错误,但这不是可取的。

使用“实体名称”属性来指定映射是诱人的,但记录不完善,似乎有一些主要缺点:a)它需要我重复所有其他映射为两个实体,并且b )它与来自指向Person类的其他类的多对一>关系不兼容。

有没有一个很好的方法来做到这一点,我失踪了?

回答

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

这是一个很好的建议,但我不认为它适用于我,因为我无法从SQL中测试以确定正确的映射。我需要控制应用程序层内的映射。 – brianberns 2012-02-23 19:10:27

0

即使我假设OP已经解决了他的问题在某些方面,我我想提出一个使用预测的解决方案。

基本上,你的数据访问层(DAL)您选择使用投影列表稍微复杂的方式来访问你的数据,但回到取决于你的逻辑所需的FakePersonRealPerson类的实例。

这将是这个样子:

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类这两个属性FakeNameRealName而且使protected和一个公共Name财产的人得到FakePersonRealPerson

我意识到你还是必须现在列出所有的属性两次,它已经从映射移动到了DAL。好吧,也许这可以帮助那里的人,无论如何。