具有多个“角色”的子类映射

时间:2011-08-09 15:07:36

标签: nhibernate fluent-nhibernate

一个棘手的问题 - 请耐心等待我。非常感谢任何帮助。

我有一个表/类联系人(PK Id)和两个派生的客户端和债务人(PK和FK ContactId)。第4表案例具有债务人和客户的外键(下面的映射)。

一开始一切都很好。但后来我点击了一些数据,其中同一个联系人是一个案件中的客户,而另一个案件中是债务人。如果在一个nhibernate查询中读取它们,如Session.Query<Case>().Fetch(c => c.Debtor).Fetch(c => c.Client) 有一个

NHibernate.WrongClassException
    "Object with id: {someGuid...} was not of the specified subclass: Client 
    (loading object was of wrong class [Debtor])

似乎会话第一级缓存通过它的Id识别记录并尝试避免从sql结果集中读取数据。当然,演员NH认为重用失败是必要的。

不幸的是,更改数据库架构不是一种选择。这是一个遗留系统。 (一个架构是可以的,干净的IMO)

不知道它是否重要:班级联系不是抽象的。使用的联系人既不是客户也不是债务人。

是否有机会与这些多角色联系人合作?提前谢谢。

public partial class ContactMap : ClassMap<Contact>
{
    public ContactMap()
    {
    Id(x=>x.Id).GeneratedBy.Guid();
    Map(x=>x.FirstName);
    Map(x=>x.Name1).Not.Nullable();
        ...
    }
}
public class DebtorMap : SubclassMap<Debtor>
{

    public DebtorMap()
    {
        KeyColumn("ContactID");
        Table("[dbo].[Debtor]");
        Map(x => x.MaritalStatus);
        ...
    }
}

public partial class ClientMap : SubclassMap<Client>
{

    public ClientMap()
    {
        KeyColumn("ContactID");            
        Map(x => x.ClientNo).Not.Nullable();
        ...
    }
}

public partial class CaseMap : ClassMap<Case>
   public CaseMap()
   {
       ...
       References<Client>(x=>x.Client)
       References<Debtor>(x=>x.Debtor)
       ...
    }    

1 个答案:

答案 0 :(得分:0)

如果您可以向架构添加视图,则可以创建一个名为Roles的视图,该视图将客户端和Debtor记录联合起来。然后,您可以更改对象模型以表示角色:

class Contact
{
    public virtual Guid Id { get; set; }
    public virtual string FirstName { get; set; }
    public virtual ICollection<Role> Roles { get; private set; }
}

class Role
{
    public virtual Guid Id { get; set; }
}

class Client : Role
{
    public virtual string ClientNo { get; set; }
}

class Debtor : Role
{
    public virtual string MaritalStatus { get; set; }
}

class ContactMap : FluentNHibernate.Mapping.ClassMap<Contact>
{
    public ContactMap()
    {
        Table("dbo.Contacts");
        Id(x => x.Id).GeneratedBy.GuidComb();
        Map(x => x.FirstName);
        HasMany(x => x.Roles)
            .KeyColumn("ContactId")
            .Not.LazyLoad()
            .Fetch.Join();
    }
}

class RoleMap : FluentNHibernate.Mapping.ClassMap<Role>
{
    public RoleMap()
    {
        Table("dbo.Roles");
        Id(x => x.Id).GeneratedBy.GuidComb();
        this.Polymorphism.Implicit();
    }
}

class ClientMap : FluentNHibernate.Mapping.SubclassMap<Client>
{
    public ClientMap()
    {
        Table("dbo.Clients");
        KeyColumn("Id");
        Map(x => x.ClientNo);
    }
}

class DebtorMap : FluentNHibernate.Mapping.SubclassMap<Debtor>
{
    public DebtorMap()
    {
        Table("dbo.Debtors");
        KeyColumn("Id");
        Map(x => x.MaritalStatus);
    }
}

由于Contact表现在与Client和Debtor表共享一个PK,这应该有效。角色视图看起来像这样:

create view dbo.Roles as

select 
    Id,
    ContactId
from dbo.Clients

union all

select 
    Id,
    ContactId
from dbo.Debtors