使用 DiscrimminateSubClassesOnColumn 进行流畅的 NHibernate 子类映射问题

发布于 2024-12-11 22:47:50 字数 1389 浏览 0 评论 0原文

我在映射方面遇到问题,简化了我的关系,如下所示。 我有父类:

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

我的问题是,当我像这样从数据库检索行时:

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

所有行都以 < 返回code>DocumentType 属于 DocumentType 类型,而不是子类型(即该属性的实际类型,即当我执行 .GetType() 时,任何一个UploadedFileDocumentApplicationFormDocument

如果这只是我的愚昧,抱歉。但是我如何确定我拥有哪种类型的 DocumentType ...我的映射是错误的?

I have an issue with mapping, simplified my relationship looks like this.
I have parent class:

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

and two subclasses:

public class UploadedFileDocument : DocumentType
{

}

public class ApplicationFormDocument : DocumentType
{
}

mapped like this:

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>
{

}

Then I have another entity with a FK to DocumentType, mapped like this:

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

my issue is, when I retrieve rows from the DB like this:

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

all the rows come back with the DocumentType being of type DocumentType, not of the child type (ie the actual type of that property, ie. when i do .GetType(), either UploadedFileDocument or ApplicationFormDocument)

Apologies if this is just me being dim. But how can I determine which type of DocumentType I have ... is my mapping wrong?

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

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

发布评论

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

评论(1

花想c 2024-12-18 22:47:50

当您查看生成的 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):

Context

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

Specifications

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

通过断言调试,我可以看到集合返回了两个types:

DocumentType

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

When you look at your generated SQL (adding .ShowSQL() to your .Database method), do you see the Type being entered? You should see something similar to:

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

Using the mappings you provided, it looks fine and I could return the DocumentType (using SQLite) just fine.

Here's the code I used to reproduce it. I didn't have your FileConversion object, so please verify that it matches what you need.

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

The tests I used (using machine.specifications):

Context

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

Specifications

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

Debugging through the assertions, I can see that the collection comes back with the two types:

DocumentType

Are you casting them back to the base type anywhere in your mappings or classes?

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