StructureMap, NHibernate і некалькі баз дадзеных

Я працую на Asp.Net MVC 3 дадатку з дапамогай Fluent NHibernate. Я проста спрабую дадаць кантэйнер IoC з дапамогай StructureMap.

Я рэалізаваў карыстацкі кантролер завод, які выкарыстоўвае StructureMap стварыць кантролер і ўвесці залежнасці. Кожны канструктар кантролер прымае адзін або некалькі паслуг, якія, у сваю чаргу, узяць DAO як аргумент канструктара. Кожны канструктар DAO прымае ISessionFactory.

Для майго рэестра StructureMap NHibernate У мяне ёсць наступныя:

internal class NHibernateRegistry : Registry
{
    public NHibernateRegistry()
    {
        var connectionString = ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString;

        For()
                .Singleton()
                .Use(x => new AppSessionFactory().GetSessionFactory(connectionString));

        For()
            .HybridHttpOrThreadLocalScoped()
            .Use(x => x.GetInstance().OpenSession());
    }

}

public class AppSessionFactory
{
    public ISessionFactory GetSessionFactory(string connectionString)
    {
        return GetConfig(connectionString)
                .BuildSessionFactory();
    }

    public static FluentConfiguration GetConfig(string connectionString)
    {
        return Fluently.Configure()
            .Database(MsSqlConfiguration.MsSql2005.ConnectionString(x => x.Is(connectionString)))
            .Mappings(
                x => x.FluentMappings.AddFromAssemblyOf());
    }
}

Гэта ўсё працуе выдатна для адной базы дадзеных і аднаго сеансу завода. Аднак прыкладанне выкарыстоўвае некалькі баз дадзеных.

Што такое лепшы спосаб справіцца з гэтым?

7

2 адказы

Рэгістрацыя некалькіх сеансаў фабрык лёгка - праблема выбару правы аднаго, калі вам гэта трэба. Напрыклад, выкажам здагадку, што ў нас ёсць нейкі лабараторыі, якая мае некалькі баз дадзеных. Кожная лабараторыя мае Месца і некалькі узораў для гэтага месца. Мы маглі б SampleRepository, што мадэлі, якія. Кожная зона мае унікальны ключ для яго ідэнтыфікацыі (напрыклад, «LabX», «лабірын», «BlackMesa»). Мы можам выкарыстоўваць гэты ўнікальны ключ як імя радкі падлучэння да базы дадзеных у файле app.config. У гэтым прыкладзе мы будзем мець тры радкі падлучэння ў файле app.config. Вось раздзел выбарачныя ConnectionStrings:


  
  
  

Такім чынам, мы павінны мець унікальную сесійнай фабрыку для кожнага радка падключэння. Давайце створым NamedSessionFactory, які абгортвае ISessionFactory:

public interface INamedSessionFactory
{
    public string Name { get; }//The name from the config file (e.g. "BlackMesa")
    public ISessionFactory SessionFactory { get; }
}

public class NamedSessionFactory : INamedSessionFactory
{
    public string Name { get; private set; }
    public ISessionFactory SessionFactory { get; private set; }

    public NamedSessionFactory(string name, ISessionFactory sessionFactory)
    {
        Name = name;
        SessionFactory = sessionFactory;
    }
}

Цяпер нам трэба змяніць свой AppSessionFactory няшмат. Па-першае, тое, што вы стварылі гэта пасяджэнне завода завода - гэта не зусім тое, што мы шукаем. Мы хочам, каб наш завод месцазнаходжання і атрымаць сеанс з яго, не сесійнага завода. Свабодна NHibernate з'яўляецца тое, што дае нам сесію заводы.

public interface IAppSessionFactory
{
    ISession GetSessionForLocation(string locationKey);
}

Хітрасць тут прымае спіс INamedSessionFactory аб'ектаў у канструктару. StructureMap павінны даць нам усё INamedSessionFactory аб'ектаў, якія мы зарэгістравалі. Мы дабяромся да рэгістрацыі ў секунду.

public class AppSessionFactory : IAppSessionFactory
{
    private readonly IList _factories;

    public AppSessionFactory(IEnumerable(factories);
    }

Гэта дзе адбываецца чараўніцтва. Улічваючы ключавое месца, мы праводзім праз наш спіс заводаў, гледзячы на ​​адзін з тым жа імем, locationKey, затым папытаеце яго, каб адкрыць сесію і вярнуць яго да абанента.

    public ISession GetSessionForLocation(string locationKey)
    {
        var sessionFactory = _factories.Where(x => x.Name == locationKey).Single();

        return sessionFactory.OpenSession();
    }
}

Зараз давайце тэлеграму усё гэта разам.

internal class NHibernateRegistry : Registry
{
    public NHibernateRegistry()
    {

Мы будзем перабрацца ўсе радкі злучэння ў нашым файле app.config (было бы тры з іх у гэтым прыкладзе) і зарэгістраваць INamedSessionFactory аб'екта для кожнага з іх.

        foreach (ConnectionStringSettings location in ConfigurationManager.ConnectionStrings)
        {
            For()
                .Singleton()
                .Use(x => new NamedSessionFactory(
                    location.Name,
                    GetSessionFactory(location.ConnectionString));
        }

Мы таксама павінны зарэгістраваць IAppSessionFactory.

        For()
          .Singleton()
          .Use();
    }

Вы заўважыце, што мы перамясцілі гэтую логіку з класа фабрыкі ... Гэтыя дапаможныя метады для стварэння сеансавых заводаў з Fluent NHibernate.

    private static ISessionFactory GetSessionFactory(string connectionString)
    {
        return GetConfig(connectionString)
                .BuildSessionFactory();
    }

    public static FluentConfiguration GetConfig(string connectionString)
    {
        return Fluently.Configure()
            .Database(MsSqlConfiguration.MsSql2005.ConnectionString(x => x.Is(connectionString)))
            .Mappings(
                x => x.FluentMappings.AddFromAssemblyOf());
    }
}

Гэта павінна зрабіць гэта! Давайце створым рэпазітар для атрымання ў нашых узорах ...

public class SampleRepository
{
    private readonly IAppSessionFactory _factory;

    public SampleRepository(IAppSessionFactory factory)
    {
        _factory = factory;
    }

    public IEnumerable GetSamplesForLocation(Location location)
    {
        using (ISession session = _factory.GetSessionForLocation(location.Key)
        {
            foreach (Sample sample in session.Query())
              yield return sample;
        }
    }
}

Цяпер вы можаце атрымаць адзін асобнік SampleRepository і выкарыстоўваць метад GetSamplesForLocation выцягнуць ўзоры з любых з трох баз дадзеных мы зарэгістраваліся ў app.config. Можа хацець пазбегнуць BlackMesa хоць. Я разумею, што былі праблемы там.

9
дададзена
Сапраўды карысны адказ. Я ў цяперашні час выкарыстоўваю TheInstanceNamed StrucutreMap (у) прызначыць SessionFactories для DAO, які, здаецца, працуе нармальна. Будзе выглядаць да рэалізацыі вашых прапаноў, калі ў мяне ёсць трохі вольнага часу. Дзякуючы.
дададзена аўтар TonE, крыніца
Я, верагодна, варта адзначыць, што гэта было гадоў з тых часоў я выкарыстаў StructureMap або NHibernate - так што я мог бы ўшрубоўваецца нешта там. Але асноўны шаблон павінен быць гук. Спадзяюся, што гэта дапамагае!
дададзена аўтар Andy S, крыніца

Вы ўпэўненыя, што гэтая рэч працуе? <Моцны> радок ISessionFactory

public string ISessionFactory SessionFactory { get; private set; }

гэта павінна быць

public interface INamedSessionFactory
{
    ISessionFactory SessionFactory { get; set; }
    string Name { get; }
}

public class NamedSessionFactory : INamedSessionFactory
{
    public ISessionFactory SessionFactory { get; set; }
    public string Name { get; private set; }

    public NamedSessionFactory(string Name, ISessionFactory SessionFactory)
    {
        this.Name = Name;
        this.SessionFactory = SessionFactory;
    }
}
0
дададзена