Pergunta

Depois de ter conseguido com sucesso um trabalho programa de exemplo, eu estou começando agora para fazer o trabalho real com Fluent NHibernate - tentando usar Automapping na classe do meu projeto hierarquia.

É uma aplicação de instrumentação científica, e as classes que estou mapeamento têm várias propriedades que são matrizes de flutuadores e.g.

    private float[] _rawY; 
    public virtual float[] RawY 
    { 
        get 
        { 
            return _rawY; 
        } 
        set 
        { 
            _rawY = value; 
        } 
    } 

Estas matrizes podem conter um máximo de 500 valores.

Eu não esperava Automapping ao trabalho em matrizes, mas tentou fazê-lo de qualquer maneira, com algum sucesso no início. Cada matriz foi auto mapeado para um blob (Usando SQLite), que parecia ser uma solução viável.

O primeiro problema surgiu quando eu tentei ligar saveOrUpdate na objetos contendo as matrizes - eu tenho "Não persister para flutuador []" exceções.

Então, meu pensamento seguinte foi para converter todas as minhas matrizes em ILists por exemplo

public virtual IList<float> RawY { get; set; } 

Mas agora eu recebo:

NHibernate.MappingException: Association references unmapped class: System.Single 

Desde Automapping pode lidar com listas de objetos complexos, nunca Ocorreu-me que não seria capaz de mapear listas de tipos básicos. Mas depois de fazer algumas pesquisas no Google por uma solução, este parece ser o caso. Algumas pessoas parecem ter resolvido o problema, mas o código de exemplo I serra requer mais conhecimento do NHibernate que eu tenho agora - I não entendi.

Perguntas:

1. Como posso fazer este trabalho com Automapping?

2. Além disso, é melhor para matrizes de uso ou listas para esta aplicação?

posso modificar meu aplicativo para usar, se necessário (embora eu prefiro listas).

Editar:

Eu estudei o código Mapeamento Recolha de Cordas , e vejo que há código de teste na fonte que configura um IList de cordas, por exemplo

public virtual IList<string> ListOfSimpleChildren { get; set; }

[Test] 
public void CanSetAsElement() 
{ 
    new MappingTester<OneToManyTarget>() 
        .ForMapping(m => m.HasMany(x => x.ListOfSimpleChildren).Element("columnName")) 
        .Element("class/bag/element").Exists(); 
} 

de modo que este deve ser possível usando puro Automapping, mas eu tinha zero sorte para conseguir qualquer coisa para trabalhar, provavelmente porque eu não tenho o knowlege requisito de mapeamento manualmente com NHibernate.

Começando a pensar que eu vou ter que cortar este (codificando a matriz de carros alegóricos como uma única cadeia, ou a criação de uma classe que contém uma única bóia que eu então agregada em minhas listas), a menos que alguém pode me dizer como fazê-lo corretamente.

Fim Editar

Aqui é o meu método CreateSessionFactory, se isso ajuda a formular um responder ...

    private static ISessionFactory CreateSessionFactory() 
    { 
        ISessionFactory sessionFactory = null; 


        const string autoMapExportDir = "AutoMapExport"; 
        if( !Directory.Exists(autoMapExportDir) ) 
            Directory.CreateDirectory(autoMapExportDir); 


        try 
        { 
            var autoPersistenceModel = 
                AutoMap.AssemblyOf<DlsAppOverlordExportRunData>() 
                       .Where(t => t.Namespace == "DlsAppAutomapped") 
                       .Conventions.Add( DefaultCascade.All() ) 
                ; 


            sessionFactory = Fluently.Configure() 
                .Database(SQLiteConfiguration.Standard 
                              .UsingFile(DbFile) 
                              .ShowSql() 
                         ) 
                .Mappings(m => m.AutoMappings.Add(autoPersistenceModel) 
                                             .ExportTo(autoMapExportDir) 
                         ) 
                .ExposeConfiguration(BuildSchema) 
                .BuildSessionFactory() 
                ; 
        } 
        catch (Exception e) 
        { 
            Debug.WriteLine(e); 
        } 


        return sessionFactory; 
    } 
Foi útil?

Solução

Uma vez que eu postei a minha pergunta, a equipe Fluent NHibernate ter corrigido este problema.

Você pode agora AUTOMAP ILists de C # tipos de valor (strings, ints, carros alegóricos, etc).

Apenas certifique-se que você tem uma versão recente do FNH.

Editar

Eu recentemente atualizado de FNH 1,0 a FNH 1.3.

Esta versão também irá AUTOMAP matrizes -. Flutuador [], int [], etc

Parece mapeá-los como BLOBs. Eu suponho que este será mais eficiente do que ILists, mas não fizeram qualquer perfil para confirmar.

Outras dicas

Eu provavelmente faria uma relação um para muitos e fazer a lista outra mesa ...

Mas talvez você precisa repensar o seu objeto, existe também um RawX que você poderia compor em um RawPoint? Isto faria com que uma tabela com 3 colunas (ParentId, X, Y).

A descontinuidade vem de querer mapear uma lista para um valor que em um RDBMS não vai passar em uma coluna muito ordenadamente. Uma tabela é realmente o método que eles usam para armazenar listas de dados.

Este é o ponto de usar um ORM como NHibernate. Ao fazer toda a consulta e composição SQL à mão em seu aplicativo, adicionando uma mesa tinha um alto custo em manutenção e implementação. Com NHibernate o custo é de cerca de 0, a fim de aproveitar os pontos fortes do RDBMS e deixar NHibernate abstrair a feiúra de distância.


Eu vejo o seu problema com o mapeamento da matriz, experimentá-lo com um mapeamento override primeiro e ver se ele vai trabalhar, então talvez você possa criar um override convenção se quiser que o automap ao trabalho.

.Override<MyType>(map =>
{
    map.HasMany(x => x.RawY).AsList();
})

Não tenho certeza se isso vai funcionar, eu preciso para obter uma configuração de teste nHibernate configurado para este material.

Eu finalmente tenho uma substituição para o trabalho - ver o fim da lista de códigos. Os pontos-chave são:

  • uma nova classe de mapeamento chamado DlsAppOverlordExportRunDataMap
  • a adição de uma cláusula UseOverridesFromAssemblyOf em CreateSessionFactory

Além disso, verifica-se que (pelo menos com v 1.0.0.594.) Há uma grande pegadinha com Automapping - a classe de mapeamento (por exemplo DlsAppOverlordExportRunDataMap) não podem estar na mesma Namespace como a classe de domínio (por exemplo, DlsAppOverlordExportRunData)!

Caso contrário, NHibernate vai jogar "NHibernate.MappingException: (XmlDocument) (2,4): XML erro de validação: ..." , com absolutamente nenhuma indicação de que ou onde o problema real é .

Este é provavelmente um erro, e pode ser corrigido em versões posteriores do Fluent NHibernate.

namespace DlsAppAutomapped
{
    public class DlsAppOverlordExportRunData
    {
        public virtual int Id { get; set; }

        // Note: List<float> needs overrides in order to be mapped by NHibernate. 
        // See class DlsAppOverlordExportRunDataMap.
        public virtual IList<float> RawY { get; set; } 
    }
}


namespace FrontEnd
{
    // NEW - SET UP THE OVERRIDES
    // Must be in different namespace from DlsAppOverlordExportRunData!!!
    public class DlsAppOverlordExportRunDataMap : IAutoMappingOverride<DlsAppOverlordExportRunData>
    {
        public void Override(AutoMapping<DlsAppOverlordExportRunData> mapping)
        {
            // Creates table called "RawY", with primary key
            // "DlsAppOverlordExportRunData_Id", and numeric column "Value"
            mapping.HasMany(x => x.RawY)
                   .Element("Value");
        }
    }
}

    private static ISessionFactory CreateSessionFactory() 
    { 
        ISessionFactory sessionFactory = null; 


        const string autoMapExportDir = "AutoMapExport"; 
        if( !Directory.Exists(autoMapExportDir) ) 
            Directory.CreateDirectory(autoMapExportDir); 


        try 
        { 
            var autoPersistenceModel = 
                AutoMap.AssemblyOf<DlsAppOverlordExportRunData>() 
                       .Where(t => t.Namespace == "DlsAppAutomapped")

                       // NEW - USE THE OVERRIDES    
                       .UseOverridesFromAssemblyOf<DlsAppOverlordExportRunData>() 

                       .Conventions.Add( DefaultCascade.All() ) 
                ; 


            sessionFactory = Fluently.Configure() 
                .Database(SQLiteConfiguration.Standard 
                              .UsingFile(DbFile) 
                              .ShowSql() 
                         ) 
                .Mappings(m => m.AutoMappings.Add(autoPersistenceModel) 
                                             .ExportTo(autoMapExportDir) 
                         ) 
                .ExposeConfiguration(BuildSchema) 
                .BuildSessionFactory() 
                ; 
        } 
        catch (Exception e) 
        { 
            Debug.WriteLine(e); 
        } 


        return sessionFactory; 
    } 

Não obteve nenhuma resposta aqui ou na lista de discussão Fluent NHibernate que realmente funcionou, então aqui está o que eu fiz.

Tem cheiro de um hack horrível, mas funciona. (Se vai escalar até grandes restos conjuntos de dados para ser visto).

Em primeiro lugar, eu envolvi uma propriedade float (chamado Value) em uma classe:

// Hack - need to embed simple types in a class before NHibernate
// will map them
public class MappableFloat
{
    public virtual int Id { get; private set; }
    public virtual float Value { get; set; }
}

Eu, então, declarar as propriedades em outras classes que precisam ser Listas de carros alegóricos por exemplo.

public virtual IList<MappableFloat> RawYMappable { get; set; }

NHibernate cria uma tabela de banco de dados único, com múltiplas chaves estrangeiras, por exemplo.

create table "MappableFloat" (
    Id  integer,
   Value NUMERIC,
   DlsAppOverlordExportRunData_Id INTEGER,
   DlsAppOverlordExportData_Id INTEGER,
   primary key (Id)
)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top