Как использовать Nhibernate с именами переменных или динамических таблиц, такими как Jan08Tran, Feb08Tran, Mar08Tran - PullRequest
9 голосов
/ 05 февраля 2009

У меня есть устаревшая база данных, в которой таблицы транзакций хранятся по ежемесячным именам.

например.

     Jan08Tran
     Feb08Tran

Как я могу использовать NHibernate для работы с этими таблицами?

Прочитайте немного о свойстве имени объекта, подклассе и т. Д. Но не можете найти конкретное решение.

Ответы [ 7 ]

20 голосов
/ 24 июня 2009

У меня была похожая ситуация, когда мне приходилось предоставлять интерфейс между купленными приложениями, которые были в производстве и использовались тоннами различных систем. Эта система имела разные имена таблиц в dev, test и prod (смешно ...). Моим решением было оставить заполнитель для номера таблицы в конфигурации NHibernate следующим образом:

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

А затем реализовать INamingStrategy, аналогично:

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

А затем установите стратегию именования в конфигурации:

myConfiguration.SetNamingStrategy(new MyCustomNamingStrategy());

Таким образом, номер таблицы можно сохранить в App.config, а приложение можно перемещать по средам, изменяя только значения в App.config. Я уверен, что вы могли бы найти способ использовать это, чтобы изменить имя таблицы на любую нужную вам дату ...

2 голосов
/ 19 марта 2009

У меня была точно такая же проблема, и мой подход состоял в том, чтобы обновить значения конфигурации NHibernate во время выполнения. Таким образом, я мог решить, с какой из моих таблиц с одинаковыми именами я буду разговаривать. Основа техники такова: -

private static void SetTableMapping(Configuration config, 
     Type persistentClass, string newTableName)
{
    PersistentClass classMapping = config.GetClassMapping(persistentClass);
    Table physicalTable = classMapping.RootTable;
    physicalTable.Name = newTableName;
}
1 голос
/ 01 февраля 2012
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
}
1 голос
/ 07 февраля 2009

Много искал, но ничего конкретного не было доступно, наконец пошагово по источнику NHibernate и нашел следующее решение. Это нелегко, но все же есть обходной путь.

  1. Создать новый класс SqlInterceptor, который реализует IInterceptor
  2. В методе OnPrepareStatement вы можете изменить Sql по своему усмотрению
  3. Затем добавьте этот SqlInterceptor в сессию, хотя configuration.SetInterceptor(new SqlInterceptor());

Ниже приведен код 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 голосов
/ 07 февраля 2009

Это не прямой ответ на ваш вопрос, но, возможно, это может быть решением в конце концов.

Может быть, вы можете добавить один или два представления в БД, чтобы все эти динамические таблицы выглядели как одна?

0 голосов
/ 05 февраля 2009

Еще один вариант - использовать пользовательский SQL для сохранения или писать sprocs для обработки постоянно меняющихся имен таблиц.

0 голосов
/ 05 февраля 2009

Святой # $% ^! =) * * Тысяча одна

Я считаю, что это может быть достигнуто с помощью пользовательского IEntityPersister, но это будет нелегкой задачей.

Я не уверен в этом, но есть ли обновляемый вид какой-либо помощи?

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