Свободное сопоставление дочерних классов NHibernate с использованием проблемы DiscriminateSubClassesOnColumn - PullRequest
1 голос
/ 27 октября 2011

У меня проблема с отображением, упрощенные мои отношения выглядят так.У меня есть родительский класс:

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

все строки возвращаются с типом DocumentTypeDocumentType, не дочернего типа (т. Е. Фактический тип этого свойства, т. Е. Когда я делаю .GetType(), либо UploadedFileDocument, либо ApplicationFormDocument)

Извинения, если это только я, смутный,Но как я могу определить, какой тип DocumentType у меня есть ... мое отображение неверно?

1 Ответ

1 голос
/ 27 октября 2011

Когда вы смотрите на ваш сгенерированный 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();
         }
     }
  };

Технические характеристики

  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

Вы приводите их обратно к базовому типу где-нибудь в ваших отображениях или классах?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...