2010-04-16 5 views
9

Il mio progetto deve gestire tre database, ovvero tre fabbriche di sessione. Il fatto è che se faccio qualcosa di simile con NHibernate fluente:Fluent NHibernate + database multipli

.Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly())) 

le fabbriche sarebbero raccogliere tutte le mappature, anche quelli che corrispondono a un altro database

ho visto che quando si utilizza si automapping può fare qualcosa di simile, e filtrare per namespace:

.Mappings(m => m.AutoMappings.Add(
    AutoMap 
     .AssemblyOf<Product>() 
     .Where(t => t.Namespace == "Storefront.Entities"))) 

I havent trovato nulla di simile per mappature fluenti, è possibile ?? Le uniche soluzioni a cui posso pensare sono: o creare assembly separati per ogni classe di mapping db o aggiungere esplicitamente ciascuna delle entità alla configurazione di fabbrica.

Preferirei evitare entrambi, se possibile. Grazie.

+2

Vorrei consigliare un assembly di mappatura per database in questa istanza. È una buona separazione di preoccupazioni e dovrebbe essere facile da comprendere per qualsiasi altro sviluppatore. –

+0

Sembra che ho bisogno di mettere tutte le classi entitiy in un altro progetto e l'altro progetto per il secondo db. – CallMeLaNN

risposta

5

Ho implementato esattamente questo usando (il mio) attributo sul file di mapping Fluent per dettare quale Db l'entità appartiene. Ho anche avuto un concetto di un database 'predefinito' e si presuppone che il mapping dei file senza un attributo risieda nel DB predefinito (potrebbe ridurre il numero di classi che è necessario decorare). Ho quindi un codice di inizializzazione che crea una Session Factory per database e, per ognuno, utilizza reflection per trovare tutte le classi ClassMap, esamina l'attributo per determinare a quale DB appartiene e registra ogni ClassMap di conseguenza.

Un esempio di file di mapping:

[FluentNHibernateDatabase("MySecurityDatabase")] 
    public class SystemUserMap : ClassMap<SystemUser> 
    { 
    public SystemUserMap() 
    { 
     Id(x => x.SystemUserId); 
     Map(x => x.LoginId); 
     Map(x => x.LoginPassword); 
     Map(x => x.UserFirstName); 
     Map(x => x.UserSurname); 
     References(x => x.UserOrganisation, "OrganisationId"); 
    } 
    } 

Ovviamente ho definito un elenco dei DB che si fa riferimento/usato.
mia implementazione lavora quanto ho preso, ma ho colpito un intoppo (che spero che qualcuno possa aiutare con):

Ho chiesto alla mia domanda qui: How to identify a particular entity's Session Factory with Fluent NHibernate and Multiple Databases

+3

In questo scenario, dove stai facendo uso dell'attributo? So che sarebbe nella configurazione di mappatura, ma c'è qualche possibilità che tu possa fornire maggiori dettagli della tua implementazione? Grazie! – reallyJim

+0

Dove si trova l'attributo FluentNHibernateDatabase e come si definisce Fluently.Configure()? – CallMeLaNN

+0

L'attributo è il mio e lo uso per identificare il DB a cui deve essere registrata una determinata classe (il parametro dell'attributo è il nome che ho dato al mio DB). Ho implementato in modo tale da avere quello che considero il DB "predefinito" e tutti i file Mappa relativi alle entità in quel DB non hanno bisogno dell'attributo (o, inversamente: si presume che tutti i file di mappa senza l'attributo siano finalizzati a il DB predefinito). – Trevor

1

È anche possibile filtrare per tipi. Ecco una riga di codice commentato da un "campo verde" AutoPersistenceModel che uso nello stesso assembly di un "campo marrone uno" (cioè due database). Ma c'è un solo tipo di filtro da filtrare, quindi non mi sono preso la briga di dividere un assembly legacy. Se ne hai molti di loro per db, allora la loro suddivisione per assembly è probabilmente la migliore IMO.

Sarebbe bello se FNH fosse in grado di fornire una sorta di supporto multi-db integrato, ma non so come sia possibile farlo realmente; forse una sorta di dizionario di SessionFactories, ma ogni situazione è così unica.

HTH,
Berryl

/// <summary> 
    /// This would simply call <see cref="AutoMapHelpers.GetAutoMappingFilter"/> but we need to 
    /// exclude <see cref="LegacyProject"/> also for now. 
    /// </summary> 
    private static bool _getIncludedTypesFilter(Type t) { 
     return _isNotLegacy(t) && AutoMapHelpers.GetAutoMappingFilter(t); 
    } 
    private static bool _isNotLegacy(Type t) { return !t.Equals(typeof(LegacyProject)); } 
4

il modo più semplice per farlo è quello di mettere il nome del database nello schema

Poi, a condizione tutte le tabelle sono accessibili sulla stessa stringa di connessione, è necessario solo una fabbrica sessione

0

Anche se è una risposta molto tarda, ti suggerisco di leggere il seguente url che ha una soluzione da risolvere e quindi puoi trovare la soluzione nelle risposte. Here è la soluzione ai vostra risposta che è stata attuata con l'aiuto di url

Con la soluzione implementata da me è possibile implementare unico database primo modello, al momento. Prova a evitare il metodo GenerateSchema nella domanda posta da me nell'indice, perché non è ancora implementato come se si usasse quel metodo, si sarà in grado di vedere i database multipli con le stesse tabelle e relazioni create.