0

通用例如:功能NHibernate,多抽象基類繼承不加載中間基類

摘要映射類A. 摘要映射B類:(或任何你想要的)A,B的類型爲int的屬性 映射C類:A.

摘要映射類d具有A型 映射E類的屬性:D.具有B型

保存E至數據庫的屬性。檢索它並嘗試從E. 訪問B.int拋出「InvalidCastException的:無法轉換類型 'AProxy' 的目的爲類型 'B'

使用FluentNhibernate:1.3.0 Nhibernate的:3.2.0.4

實際剝離下來例如:

BaseTemplate表:

USE [DB] 
GO 

SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER ON 
GO 

CREATE TABLE [temp].[BaseTemplate](
    [ID] [int] IDENTITY(1,1) NOT NULL, 
CONSTRAINT [PK_BaseTemplate] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 

MiddleTemplate表:

USE [DB] 
GO 

SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER ON 
GO 

CREATE TABLE [temp].[MiddleTemplate](
    [ID] [int] NOT NULL, 
    [MiddleTemplateProperty] [int] NULL, 
CONSTRAINT [PK_MiddleTemplate] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 

ALTER TABLE [temp].[MiddleTemplate] WITH CHECK ADD CONSTRAINT [FK_MiddleTemplate_BaseTemplate] FOREIGN KEY([ID]) 
REFERENCES [temp].[BaseTemplate] ([ID]) 
GO 

ALTER TABLE [temp].[MiddleTemplate] CHECK CONSTRAINT [FK_MiddleTemplate_BaseTemplate] 
GO 

LastTemplate表:

USE [DB] 
GO 

SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER ON 
GO 

CREATE TABLE [temp].[LastTemplate](
    [ID] [int] NOT NULL, 
    [LastTemplateProperty] [int] NULL, 
CONSTRAINT [PK_LastTemplate] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 

ALTER TABLE [temp].[LastTemplate] WITH CHECK ADD CONSTRAINT [FK_LastTemplate_BaseTemplate] FOREIGN KEY([ID]) 
REFERENCES [temp].[BaseTemplate] ([ID]) 
GO 

ALTER TABLE [temp].[LastTemplate] CHECK CONSTRAINT [FK_LastTemplate_BaseTemplate] 
GO 

BaseTemplateInstance表:

USE [DB] 
GO 


SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER ON 
GO 

CREATE TABLE [temp].[BaseTemplateInstance](
    [ID] [int] IDENTITY(1,1) NOT NULL, 
    [TemplateID] [int] NOT NULL, 
CONSTRAINT [PK_BaseTemplateInstance] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 

ALTER TABLE [temp].[BaseTemplateInstance] WITH CHECK ADD CONSTRAINT [FK_BaseTemplateInstance_BaseTemplate] FOREIGN KEY([TemplateID]) 
REFERENCES [temp].[BaseTemplate] ([ID]) 
GO 

ALTER TABLE [temp].[BaseTemplateInstance] CHECK CONSTRAINT [FK_BaseTemplateInstance_BaseTemplate] 
GO 

LastTemplateInstance表:

USE [DB] 
GO 

SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER ON 
GO 

CREATE TABLE [temp].[LastTemplateInstance](
    [ID] [int] NOT NULL, 
CONSTRAINT [PK_LastTemplateInstance] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

GO 

ALTER TABLE [temp].[LastTemplateInstance] WITH CHECK ADD CONSTRAINT [FK_LastTemplateInstance_BaseTemplateInstance] FOREIGN KEY([ID]) 
REFERENCES [temp].[BaseTemplateInstance] ([ID]) 
GO 

ALTER TABLE [temp].[LastTemplateInstance] CHECK CONSTRAINT [FK_LastTemplateInstance_BaseTemplateInstance] 
GO 

類:

public abstract class BaseTemplate 

public abstract class MiddleTemplate : BaseTemplate 
    { 
     public virtual int MiddleTemplateProperty { get; set; } 
    } 

public class LastTemplate : MiddleTemplate 
    { 
     public virtual int LastTemplateProperty { get; set; } 
    } 

public abstract class BaseTemplateInstance 
    { 
     public virtual BaseTemplate Template { get; set; } 

     protected BaseTemplateInstance() {} 
     protected BaseTemplateInstance(BaseTemplate template) : this() 
     { 
      Template = template; 
     } 
    } 

public class LastTemplateInstance : BaseTemplateInstance 
    { 
     protected LastTemplateInstance() {} 

     public LastTemplateInstance(LastTemplate template) 
      :base(template) {} 

     public virtual int MiddleTemplateProperty { get { return ((MiddleTemplate) Template).MiddleTemplateProperty; } } 
    } 

映射:

public class BaseTemplateMap : ClassMap<BaseTemplate> 
    { 
     public BaseTemplateMap() 
     { 
      Table("temp.BaseTemplate"); 

      // Unique Identifier 
      Id(x => x.Id, "ID") 
       .GeneratedBy.Identity(); 
     } 
    } 

public class MiddleTemplateMap : SubclassMap<MiddleTemplate> 
    { 
     public MiddleTemplateMap() 
     { 
      Table("temp.MiddleTemplate"); 

      KeyColumn("ID"); 

      Map(x => x.MiddleTemplateProperty) 
       .Nullable(); 
     } 
    } 


public class LastTemplateMap : SubclassMap<LastTemplate> 
    { 
     public LastTemplateMap() 
     { 
      Table("temp.LastTemplate"); 

      KeyColumn("ID"); 

      Map(x => x.LastTemplateProperty) 
       .Nullable(); 
     } 
    } 

public class BaseTemplateInstanceMap : ClassMap<BaseTemplateInstance> 
    { 
     public BaseTemplateInstanceMap() 
     { 
      Table("temp.BaseTemplateInstance"); 

      // Unique Identifier 
      Id(x => x.Id, "Id") 
       .GeneratedBy.Identity(); 

      References(x => x.Template, "TemplateID") 
       .Not.Nullable(); 
     } 
    } 

public class LastTemplateInstanceMap : SubclassMap<LastTemplateInstance> 
    { 
     public LastTemplateInstanceMap() 
     { 
      Table("temp.LastTemplateInstance"); 

      // Unique Identifier 
      KeyColumn("ID"); 
     } 
    } 

測試例:

[TestFixture] 
    internal class TempFileTests 
    { 
     #region Members 

     private LastTemplate _entity; 
     private MappingsRepository _repository; 

      #endregion // Members 

     #region SetUp 

     [TestFixtureSetUp] 
     public void SetUpFixture() 
     { 
      _repository = MappingsRepository.GetInstance(); 
     } 

     [SetUp] 
     public void SetUp() 
     { 
      _entity = new LastTemplate(); 
     } 

     #endregion // SetUp 

     #region Tests 

     [Test] 
     public void LastTemplateInstanceMappingsTest() 
     { 
      var lastTemplateInstance = new LastTemplateInstance(_entity); 
      _repository.Save(_entity); 

      lastTemplateInstance = new PersistenceSpecification<LastTemplateInstance>(_repository.CurrentSession) 
       .VerifyTheMappings(lastTemplateInstance); 

      var middleProperty = lastTemplateInstance.MiddleTemplateProperty; 
     } 

     #endregion // Tests 

     #region TearDown 

     [TearDown] 
     public void TearDown() 
     { 
      if (_entity != null && !_entity.IsNew()) 
       _repository.Delete(_entity); 
     } 

     [TestFixtureTearDown] 
     public void TearDownFixture() 
     { 
      _repository.Dispose(); 
      _repository = null; 
     } 

     #endregion // TearDown 
    } 
+0

'LastTemplateInstance.Template'在哪裏分配了一個''值? – mxmissile 2014-09-19 14:50:54

+0

LastTemplate是MiddleTemplate的類型。在LastTemplateInstance的構造函數中,我們傳遞了一個LastTemplate,你應該能夠將其轉換爲MiddleTemplate以獲取MiddleTemplateProperty。 – Seraph812 2014-09-19 15:13:34

回答

0

,就會出現問題。如果您在映射到NOT lazyLoad中設置此引用,那麼工作正常!

當前的理論是,在加載之前嘗試從它訪問屬性導致異常。確保它不是延遲加載,意味着它將被加載,允許正確的轉換,並且可以訪問屬性。

0

我看到你的失蹤BaseTemplateMap的DiscriminateSubClassesOnColumn地圖,並在MiddleTemplateMap和LastTemplateMap DiscriminatorValue地圖。一旦你讓NHibernate知道如何識別基於descriminator的類型,它應該加載正確的對象(即在你的情況下它是B類型),你的投射應該工作。試圖訪問BaseTemplateInstance.Template時

看這個sample

+0

我們使用的是「Table per Type」策略(在文章中舉例說明)。因此在這種情況下不使用鑑別​​器。 – Seraph812 2014-09-19 15:16:28

+0

只有在每個層次使用一個表時才需要使用鑑別符。 OP正在使用多個表格。 – mxmissile 2014-09-19 15:18:04