2009-02-05 9 views
9

Dispongo di un database precedente in cui le tabelle delle transazioni sono archiviate con nomi mensili.Come utilizzare Nhibere con nomi di tabelle dinamiche o variabili come Jan08Tran, Feb08Tran, Mar08Tran

es.

 Jan08Tran 
    Feb08Tran 

Come posso utilizzare NHibernate per lavorare con queste tabelle?

Leggere un po 'di proprietà nome-entità, sottoclasse ecc. Ma non è possibile trovare una soluzione concreta.

+0

no. no. no. Lo schema del tuo DB è sbagliato. Non farlo ai tavoli. non c'è una buona ragione per cui (per farlo), mai. Aggiungi in una colonna della data che memorizza la data della transazione. Se sei preoccupato per il clustering/partizionamento - la colonna della data diventa il punto di pivot. – jim

+5

Grazie Jim per la preoccupazione. Ma come ho detto questo è un database legacy e non posso cambiarlo ora come è nella pubblicità di produzione utilizzata da almeno 400 dei miei clienti. –

+0

Quale DB? In teoria è possibile passare a una singola tabella partizionata con una colonna della data e quindi creare viste per ogni tabella di un mese e questo risolverà il problema di ibernazione e altri problemi. – jim

risposta

20

ho avuto una situazione simile in cui ho dovuto fornire un'interfaccia tra le applicazioni acquistate che erano in produzione e utilizzati da tonnellate di sistemi diversi. Questo sistema aveva nomi di tabelle diversi per tutto lo sviluppo, il test e il pungolo (ridicolo ...) La mia soluzione era quella di lasciare un segnaposto per il numero di tabella nel config NHibernate in questo modo:

<class name="MyClass" table="MyTable[tableNumber]"> 

e quindi implementare INamingStrategy simile a:

public class MyCustomNamingStrategy : INamingStrategy 
{ 
    public string ClassToTableName(string className) 
    { 
     return DefaultNamingStrategy.Instance.ClassToTableName(className); 
    } 

    public string PropertyToColumnName(string propertyName) 
    { 
     return DefaultNamingStrategy.Instance.PropertyToColumnName(propertyName); 
    } 

    public string TableName(string tableName) 
    { 
     tableName = tableName.Replace("[tableNumber]", LocalSettings.TableNumber); 
     return DefaultNamingStrategy.Instance.TableName(tableName); 
    } 

    public string ColumnName(string columnName) 
    { 
     return DefaultNamingStrategy.Instance.ColumnName(columnName); 
    } 

    public string PropertyToTableName(string className, string propertyName) 
    { 
     return DefaultNamingStrategy.Instance.PropertyToTableName(className, propertyName); 
    } 

    public string LogicalColumnName(string columnName, string propertyName) 
    { 
     return DefaultNamingStrategy.Instance.LogicalColumnName(columnName, propertyName); 
    } 
} 

e quindi impostare la strategia di denominazione nella configurazione:

myConfiguration.SetNamingStrategy(new MyCustomNamingStrategy()); 

questo modo il numero tabella potrebbe essere memorizzato nella App.config e l'applicazione potrebbe essere spostato in ambienti da solo cambiando valori nella App.conf ig. Sono sicuro che potresti trovare un modo per usarlo per cambiare il nome della tabella in qualunque data tu avessi bisogno ...

+0

davvero fantastico: D –

+0

Dove impostare la strategia di denominazione nella configurazione? E possiamo usare entrambe le opzioni di NHibernate come il nome fisico diretto che specifica e assegnare dinamicamente il nome in un singolo progetto con un singolo database –

0

Holy # $% ^! =)

Ritengo che ciò possa essere ottenuto con l'ordinazione IEntityPersister, ma questo non sarebbe un compito facile.

Non ne sono sicuro, ma è una vista aggiornabile di qualsiasi aiuto?

0

Un'altra opzione è utilizzare SQL personalizzato per eseguire la persistenza o scrivere sproc per gestire i nomi delle tabelle che cambiano continuamente.

+0

Sì, ho pensato ma SQL personalizzato o sprocs sfideranno il reale vantaggio dell'utilizzo di NHibernate –

1

Ha cercato un sacco ma non è stato disponibile nulla di specifico, infine è stato fatto un passo sulla riga del generatore NHibernate e trovato la seguente soluzione. Questo non è facile ma ha ancora un problema.

  1. Creare un nuovo classs SqlInterceptor che implementa IInterceptor
  2. Nel metodo OnPrepareStatement è possibile modificare l'SQL come si desidera
  3. Quindi aggiungere questo SqlInterceptor a Sesion se configuration.SetInterceptor(new SqlInterceptor());

seguito è il codice per SqlInterceptor

using System; 
using System.Collections; 
using NHibernate.SqlCommand; 
using NHibernate.Type; 

namespace NHibernate 
{ 
    [Serializable] 
    public class SqlInterceptor : IInterceptor 
    { 
     public virtual void OnDelete(object entity, object id, object[] state, string[] propertyNames, IType[] types) 
     { 
     } 

     public void OnCollectionRecreate(object collection, object key) 
     { 
     } 

     public void OnCollectionRemove(object collection, object key) 
     { 
     } 

     public void OnCollectionUpdate(object collection, object key) 
     { 
     } 

     public virtual bool OnFlushDirty(object entity, object id, object[] currentState, object[] previousState, 
             string[] propertyNames, IType[] types) 
     { 
      return false; 
     } 

     public virtual bool OnLoad(object entity, object id, object[] state, string[] propertyNames, IType[] types) 
     { 
      return false; 
     } 

     public virtual bool OnSave(object entity, object id, object[] state, string[] propertyNames, IType[] types) 
     { 
      return false; 
     } 

     public virtual void PostFlush(ICollection entities) 
     { 
     } 

     public virtual void PreFlush(ICollection entitites) 
     { 
     } 

     public virtual bool? IsTransient(object entity) 
     { 
      return null; 
     } 

     public virtual object Instantiate(string clazz, EntityMode entityMode, object id) 
     { 
      return null; 
     } 

     public string GetEntityName(object entity) 
     { 
      return null; 
     } 

     public object GetEntity(string entityName, object id) 
     { 
      return null; 
     } 

     public virtual int[] FindDirty(object entity, object id, object[] currentState, object[] previousState, 
             string[] propertyNames, IType[] types) 
     { 
      return null; 
     } 

     public virtual void AfterTransactionBegin(ITransaction tx) 
     { 
     } 

     public virtual void BeforeTransactionCompletion(ITransaction tx) 
     { 
     } 

     public virtual void AfterTransactionCompletion(ITransaction tx) 
     { 
     } 

     public virtual void SetSession(ISession session) 
     { 
     } 

     public SqlString OnPrepareStatement(SqlString sql) 
     { 
      ///Do something fancy here like 
      ///sql.Replace("_MonTranTable_", MonthName + "Tran"); 
      return sql; 
     } 
    } 
} 
0

Questa non è una risposta diretta alla tua domanda, ma forse può essere una soluzione, dopo tutto.

Forse è possibile aggiungere una vista o due al DB che farà sembrare tutti quei tavoli dinamici come uno?

+0

Ma quelle tabelle non sono fisse come ho detto "Dinamico" quindi ho bisogno di una logica dal codice stesso ... A partire da ora sono in grado per ottenere la mia soluzione desiderata. Sto ulteriormente perfezionandolo e aggiornerò i progressi –

2

Avevo lo stesso identico problema e il mio approccio era di aggiornare i valori di configurazione di NHibernate in fase di esecuzione. In questo modo ho potuto decidere quale delle mie numerose tabelle con nomi identici avrei parlato. La base della tecnica è questa: -

private static void SetTableMapping(Configuration config, 
    Type persistentClass, string newTableName) 
{ 
    PersistentClass classMapping = config.GetClassMapping(persistentClass); 
    Table physicalTable = classMapping.RootTable; 
    physicalTable.Name = newTableName; 
} 
1
public class NHibernateHelper 
{  
    private static ISessionFactory _sessionFactory; 

    private static ISessionFactory SessionFactory 
    { 
     get 
     { 
      if (_sessionFactory == null) 
      { 
       Configuration configuration = new Configuration(); 
       configuration.Configure(); 

      // configuration.AddAssembly(typeof(clsDocumentMaster).Assembly); 
       configuration.SetNamingStrategy(new MyClass()); 
       configuration.AddFile("clsDocumentMaster.hbm.xml"); 
       //configuration.AddFile("Level15.hbm.xml"); 

       _sessionFactory = configuration.BuildSessionFactory(); 
      } 
      return _sessionFactory; 
     } 
    } 
    public static ISession OpenSession() 
    { 
     return SessionFactory.OpenSession(); 
    } 
} 

public class MyClass : INamingStrategy 
{ 
    #region INamingStrategy Members 

    public string ClassToTableName(string className) 
    { 
     return DefaultNamingStrategy.Instance.ClassToTableName(className); 
    } 

    public string ColumnName(string columnName) 
    { 
     return DefaultNamingStrategy.Instance.ColumnName(columnName); 
    } 

    public string LogicalColumnName(string columnName, string propertyName) 
    { 
     return DefaultNamingStrategy.Instance.LogicalColumnName(columnName, propertyName); 
    } 

    public string PropertyToColumnName(string propertyName) 
    { 
     return DefaultNamingStrategy.Instance.PropertyToColumnName(propertyName); 
    } 

    public string PropertyToTableName(string className, string propertyName) 
    { 
     return DefaultNamingStrategy.Instance.PropertyToTableName(className, propertyName); 
    } 

    public string TableName(string tableName) 
    { 
     if (tableName.IndexOf("[TagtableName]") > -1) 
      tableName = tableName.Replace("[TagtableName]", "TAG1"); 
     else 
      tableName = DefaultNamingStrategy.Instance.TableName(tableName); 

     return DefaultNamingStrategy.Instance.TableName(tableName); 

    } 

    #endregion 
} 
Problemi correlati