使用DiscriminateSubClassesOnColumn问题流畅的NHibernate子类映射

时间:2011-10-27 11:11:02

标签: c# asp.net-mvc nhibernate fluent-nhibernate

我遇到了映射问题,简化了我的关系。 我有父类:

public abstract class DocumentType
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
}

和两个子类:

public class UploadedFileDocument : DocumentType
{

}

public class ApplicationFormDocument : DocumentType
{
}

像这样映射:

public DocumentTypeMap()
{
    Schema("Core");
    Id(x => x.Id);
    Map(x => x.Name).Length(128).Not.Nullable();
    DiscriminateSubClassesOnColumn("Type");
}

public class UploadedFileDocumentMap : SubclassMap<UploadedFileDocument>
{

}

public class ApplicationFormDocumentMap : SubclassMap<ApplicationFormDocument>
{

}

然后我有另一个带有FK到DocumentType的实体,映射如下:

public FileConversionMap()
{
    Schema("Core");
    Id(x => x.Id);
    References(x => x.Application).Not.Nullable();
    References(x => x.DocumentType).Not.Nullable().Fetch.Select();           
}

我的问题是,当我从DB中检索行时:

Session.Query<FileConversion>().AsQueryable();

所有行返回时DocumentType类型为DocumentType,而不是子类型(即该属性的实际类型,即当我执行.GetType()时, UploadedFileDocumentApplicationFormDocument

道歉,如果这只是我昏暗。但是,如何确定我所拥有的DocumentType哪种类型......我的映射是错误的?

1 个答案:

答案 0 :(得分:1)

当您查看生成的SQL(向.ShowSQL()方法添加.Database)时,您是否看到输入的类型?你应该看到类似的东西:

INSERT 
INTO
    "Core_DocumentType"
    (Name, Type) 
VALUES
    (@p0, 'ApplicationFormDocument');
select
    last_insert_rowid();
@p0 = 'afd' [Type: String (0)]

使用您提供的映射,它看起来很好,我可以返回DocumentType(使用SQLite)就好了。

这是我用来重现它的代码。我没有您的FileConversion对象,因此请确认它符合您的需要。

<强> DocumentType

public class DocumentType
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
}

public class DocumentTypeMap : ClassMap<DocumentType>
{
    public DocumentTypeMap()
    {
        GenerateMap();
    }

    void GenerateMap()
    {
        Schema("Core");
        Id(x => x.Id).GeneratedBy.Identity();
        Map(x => x.Name).Length(128).Not.Nullable();
        DiscriminateSubClassesOnColumn("Type");
    }
}

<强> UploadFileDocument / ApplicationFormDocument

public class UploadedFileDocument : DocumentType
{
    public virtual string ContentType { get; set; }
}

public class ApplicationFormDocument : DocumentType
{
}

public class UploadFileDocumentMap : 
             SubclassMap<UploadedFileDocument>
{
    public UploadFileDocumentMap()
    {
        GenerateMap();
    }

    void GenerateMap()
    {
        Map(x => x.ContentType);
    }
}

public class ApplicationFormDocumentMap : 
             SubclassMap<ApplicationFormDocument>
{
}

<强> FileConversion

public class FileConversion
{
    public virtual int Id { get; set; }
    public virtual DocumentType DocumentType { get; set; }
}

public class FileConversionMap : ClassMap<FileConversion>
{
    public FileConversionMap()
    {
        GenerateMap();
    }

    void GenerateMap()
    {
        Schema("Core");
        Id(x => x.Id).GeneratedBy.Identity();
        References(x => x.DocumentType).Not.Nullable().Fetch.Select();
    }
}

我使用的测试(使用machine.specifications):

<强>上下文

public class when_discriminating_on_subclass
{
   static IList<FileConversion> results;
   Establish context = () =>
   {
      using (var session = DataConfiguration.CreateSession())
      {
         using (var transaction = session.BeginTransaction())
         {
            var upload = new UploadedFileDocument 
                             { Name = "uploaded", ContentType = "test" };
            var form = new ApplicationFormDocument 
                             { Name = "afd" };
            session.Save(form);
            session.Save(upload);

            var formConversion = 
                new FileConversion { DocumentType = form };
            var uploadConversion = 
                new FileConversion { DocumentType = upload };
            session.Save(formConversion);
            session.Save(uploadConversion);

            transaction.Commit();
         }
         using (var transaction = session.BeginTransaction())
         {
            results = session.Query<FileConversion>().AsQueryable().ToList();
            transaction.Commit();
         }
     }
  };

<强>规格

  It should_return_two_results = () =>
     results.Count.ShouldEqual(2);

  It should_contain_one_of_type_uploaded_file = () => 
     results
         .Count(x => x.DocumentType.GetType() == typeof(UploadedFileDocument))
         .ShouldEqual(1);

  It should_contain_one_of_type_application_form = () => 
     results
         .Count(x => x.DocumentType.GetType() == typeof(ApplicationFormDocument))
         .ShouldEqual(1);
}

通过断言进行调试,我可以看到该集合有两种类型:

DocumentType

您是否将它们转换回映射或类中任何位置的基类型?