Đăng ký nhiều nhà máy phiên là dễ dàng - sự cố đang chọn đúng nhà máy khi bạn cần. Ví dụ, giả sử chúng ta có một số loại phòng thí nghiệm có nhiều cơ sở dữ liệu. Mỗi phòng thí nghiệm có một Vị trí và nhiều Mẫu cho vị trí đó. Chúng tôi có thể có một SampleRepository mô hình đó. Mỗi Vị trí có một khóa duy nhất để xác định nó (ví dụ: "LabX", "LabY", "BlackMesa"). Chúng ta có thể sử dụng khóa duy nhất đó làm tên của chuỗi kết nối cơ sở dữ liệu trong tệp app.config. Trong ví dụ này, chúng ta sẽ có ba chuỗi kết nối trong tệp app.config. Đây là phần connectionStrings mẫu:
<connectionStrings>
<add name="LabX" connectionString="Data Source=labx;User ID=someuser;Password=somepassword"/>
<add name="LabY" connectionString="Data Source=laby;User ID=someuser;Password=somepassword"/>
<add name="BlackMesa" connectionString="Data Source=blackmesa;User ID=freemang;Password=crowbar"/>
</connectionStrings>
Vì vậy, chúng tôi cần phải có nhà máy phiên duy nhất cho mỗi chuỗi kết nối. Hãy tạo một NamedSessionFactory kết thúc tốt đẹp 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;
}
}
Bây giờ chúng ta cần phải sửa đổi AppSessionFactory của bạn một chút. Trước hết, những gì bạn đã tạo là một nhà máy sản xuất nhà máy - đó không phải là những gì chúng tôi đang tìm kiếm. Chúng tôi muốn cung cấp cho một nhà máy của chúng tôi một vị trí và có được một phiên làm việc của nó, không phải là một nhà máy phiên. Fluiber NHibernate là những gì mang lại cho chúng tôi các nhà máy phiên.
public interface IAppSessionFactory
{
ISession GetSessionForLocation(string locationKey);
}
Bí quyết ở đây là chấp nhận danh sách đối tượng INamedSessionFactory trong hàm tạo. StructureMap sẽ cung cấp cho chúng ta tất cả các đối tượng INamedSessionFactory mà chúng ta đã đăng ký. Chúng tôi sẽ đăng ký trong một giây.
public class AppSessionFactory : IAppSessionFactory
{
private readonly IList<INamedSessionFactory> _factories;
public AppSessionFactory(IEnumerable<INamedSessionFactory factories)
{
_factories = new List<INamedSessionFactory>(factories);
}
Đây là nơi ma thuật xảy ra. Với khóa vị trí, chúng tôi chạy qua danh sách các nhà máy tìm kiếm một nhà máy có cùng tên với locationKey, sau đó yêu cầu mở một phiên và trả lại cho người gọi.
public ISession GetSessionForLocation(string locationKey)
{
var sessionFactory = _factories.Where(x => x.Name == locationKey).Single();
return sessionFactory.OpenSession();
}
}
Bây giờ chúng ta hãy kết nối tất cả lại với nhau.
internal class NHibernateRegistry : Registry
{
public NHibernateRegistry()
{
Chúng ta sẽ để lặp qua tất cả các chuỗi kết nối trong file app.config của chúng tôi (sẽ có ba trong số họ trong ví dụ này) và đăng ký một đối tượng INamedSessionFactory cho mỗi một.
foreach (ConnectionStringSettings location in ConfigurationManager.ConnectionStrings)
{
For<INamedSessionFactory>()
.Singleton()
.Use(x => new NamedSessionFactory(
location.Name,
GetSessionFactory(location.ConnectionString));
}
Chúng tôi cũng cần đăng ký IAppSessionFactory.
For<IAppSessionFactory>()
.Singleton()
.Use<AppSessionFactory>();
}
Bạn sẽ nhận thấy rằng chúng tôi đã chuyển logic này ra khỏi lớp nhà máy ...Đây là các phương thức trợ giúp để tạo các nhà máy phiên từ 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<AppEntity>());
}
}
Điều đó sẽ làm được! Hãy tạo một kho lưu trữ để nhận tại mẫu của chúng tôi ...
public class SampleRepository
{
private readonly IAppSessionFactory _factory;
public SampleRepository(IAppSessionFactory factory)
{
_factory = factory;
}
public IEnumerable<Sample> GetSamplesForLocation(Location location)
{
using (ISession session = _factory.GetSessionForLocation(location.Key)
{
foreach (Sample sample in session.Query<Sample>())
yield return sample;
}
}
}
Bây giờ bạn có thể nhận được một trường hợp duy nhất của SampleRepository và sử dụng phương pháp GetSamplesForLocation để kéo mẫu từ một trong ba cơ sở dữ liệu, chúng tôi đã đăng ký trong app.config. Có thể muốn tránh BlackMesa. Tôi hiểu có vấn đề ở đó.
tôi có lẽ nên lưu ý rằng nó được năm kể từ khi tôi đã sử dụng StructureMap hoặc NHibernate - vì vậy tôi có thể đã hơi say một cái gì đó trên đó. Nhưng các mô hình cơ bản nên được âm thanh. Hy vọng nó giúp! –
Câu trả lời thực sự hữu ích. Tôi hiện đang sử dụng TheInstanceNamed của StrucutreMap() để gán SessionFactories cho DAO, có vẻ như hoạt động tốt. Sẽ xem xét để thực hiện các đề xuất của bạn khi tôi có một chút thời gian rảnh rỗi. Cảm ơn. – TonE