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

发布于 2024-11-28 19:57:02 字数 1549 浏览 1 评论 0原文

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

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

一开始一切都很好。但后来我发现一些数据,其中同一联系人在一个案例中是客户,但在另一个案例中是债务人。如果这些是在一个 nhibernate 查询中读取的,例如 Session.Query().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认为重用失败是必要的。

不幸的是,更改数据库模式不是一个选项。这是一个遗留系统。 (在我看来,模式是好的并且干净)

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

有没有机会让它与这些多角色联系人一起工作?提前致谢。

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)
       ...
    }    

a tricky problem - please bear with me. Any help greatly appreciated.

I have a table/class Contact (PK Id) and two derived Client and Debtor (PK and FK ContactId). The 4th table Case has foreign keys to Debtor and Client (mappings below).

Everything worked fine at first. But then I hit some data where the same Contact is a Client in one Case but a Debtor in another. If those are read in one nhibernate query like Session.Query<Case>().Fetch(c => c.Debtor).Fetch(c => c.Client)
there is a

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

Seems like the session first level cache is recognizing the record by it's Id and tries to avoid reading the data from the sql result set. Of course the cast NH thinks is necessary for the reuse fails.

Unfortunately changing the DB schema is not an option. It's a legacy system. (an the schema is ok and clean IMO)

Don't know if it is important: The class Contact is not abstract. There are Contacts used who are neither Client nor Debtor.

Is there any chance of getting this to work with these multi-role-contacts? Thanks in advance.

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)
       ...
    }    

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

渔村楼浪 2024-12-05 19:57:02

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

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);
    }
}

由于联系人表现在与客户表和债务人表共享 PK,因此这应该可行。角色视图看起来像这样:

create view dbo.Roles as

select 
    Id,
    ContactId
from dbo.Clients

union all

select 
    Id,
    ContactId
from dbo.Debtors

If you can add a view to the schema, you can create a view called Roles which unions both Client and Debtor records. You can then change your object model to represent roles:

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);
    }
}

Since the Contact table does now share a PK with Client and Debtor tables this should work. The Roles view would look something like this:

create view dbo.Roles as

select 
    Id,
    ContactId
from dbo.Clients

union all

select 
    Id,
    ContactId
from dbo.Debtors
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文