NHibernate:到单个表的多个映射

NHibernate:到单个表的多个映射,nhibernate,mapping,Nhibernate,Mapping,我有一个类,出于隐私考虑,我想以两种不同的方式映射到一个表。让我们假设这个类看起来像这样: 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 nul

我有一个类,出于隐私考虑,我想以两种不同的方式映射到一个表。让我们假设这个类看起来像这样:

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
)
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>());
相应的数据库表如下所示:

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
)
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>());
我需要的两个映射是:

  • Name属性到RealName
  • Name属性到FakeName
在这两种情况下,所有其他属性的映射都应相同。我强烈希望不必重复这些其他属性的映射

我尝试过几种不同的方法,但都没有成功。使用隔离不同映射失败,出现以下错误:DuplicateMappingException:Duplicate table mapping Person。我可以创建两个不同的数据库视图,并分别映射到它们,以避免重复表映射错误,但这并不可取

使用“entity name”属性来指定映射很有诱惑力,但文档记录得很差,似乎有一些主要缺点:a)需要我为两个实体重复所有其他映射,b)它与引用Person类的其他类的关系不兼容


有没有一个好方法可以做到这一点,我错过了

您可以使用NHibernate公式属性来匹配Name属性,如下所示

<property name="Name" formula="(SELECT id,(CASE WHEN yourcondition then RealName else FakeName end) as Name FROM Person)"/>


公式您可以引用-

您可以使用NHibernate公式属性来匹配Name属性,如下所示

<property name="Name" formula="(SELECT id,(CASE WHEN yourcondition then RealName else FakeName end) as Name FROM Person)"/>


公式你可以参考-

即使我认为OP已经以某种方式解决了他的问题,我还是想提出一个使用投影的解决方案

基本上,在您的数据访问层(DAL)中,您可以选择一种稍微复杂一点的方式来使用投影列表访问您的数据,但根据您的逻辑,您可以返回所需的
FakePerson
RealPerson
类的实例

它看起来像这样:

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
)
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>());
FakePerson别名=null;
var person=\u session.QueryOver()
.SelectList(list=>list
.Select(go=>go.Id).WithAlias(()=>alias.Id)
.Select(go=>go.FakeName).WithAlias(()=>alias.Name)//go.Other.WithAlias(()=>alias.Other)
.TransformUsing(Transformers.AliasToBean());
您仍然可以将您的
Person
类映射为两个属性
FakeName
RealName
,但要使它们
受保护
,并从具有公共
Name
属性的Person派生
FakePerson
RealPerson


我意识到现在仍然需要列出两次所有属性,它刚刚从映射转移到DAL。好吧,不管怎样,也许这对某些人有帮助。

尽管我认为OP已经以某种方式解决了他的问题,但我还是想提出一个使用投影的解决方案

基本上,在您的数据访问层(DAL)中,您可以选择一种稍微复杂一点的方式来使用投影列表访问您的数据,但根据您的逻辑,您可以返回所需的
FakePerson
RealPerson
类的实例

它看起来像这样:

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
)
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>());
FakePerson别名=null;
var person=\u session.QueryOver()
.SelectList(list=>list
.Select(go=>go.Id).WithAlias(()=>alias.Id)
.Select(go=>go.FakeName).WithAlias(()=>alias.Name)//go.Other.WithAlias(()=>alias.Other)
.TransformUsing(Transformers.AliasToBean());
您仍然可以将您的
Person
类映射为两个属性
FakeName
RealName
,但要使它们
受保护
,并从具有公共
Name
属性的Person派生
FakePerson
RealPerson


我意识到现在仍然需要列出两次所有属性,它刚刚从映射转移到DAL。好吧,不管怎样,这可能对其他人有所帮助。

这是一个很好的建议,但我认为它对我不起作用,因为我无法从SQL内部测试任何条件来确定正确的映射。我需要从应用层内部控制映射。这是一个很好的建议,但我认为它对我不起作用,因为我无法从SQL内部测试条件来确定正确的映射。我需要从应用层内部控制映射。