Tôi nghĩ tôi sẽ nhận được câu hỏi này ngoài kia trong khi tôi tự giải quyết một giải pháp.Quản lý nhiều cơ sở dữ liệu với NHibernate và Autofac
Sau khi đã xây dựng phần lớn ứng dụng, tôi có yêu cầu phút cuối để hỗ trợ đọc/ghi vào cơ sở dữ liệu bổ sung (tổng cộng 2, không biết người khác). Tôi đã xây dựng ứng dụng bằng NHibernate, với Autofac cung cấp các thành phần DI/IoC. FWIW, điều này nằm trong một ứng dụng ASP.NET MVC 2.
Tôi có một lớp lưu trữ chung có phiên NHibernate. Về mặt lý thuyết, tôi có thể tiếp tục sử dụng kho lưu trữ chung này (IRepository<>
) cho cơ sở dữ liệu thứ hai miễn là phiên được truyền cho nó được sinh ra từ một SessionFactory thích hợp, đúng không?
Vâng, khi ứng dụng bắt đầu, Autofac sẽ làm việc đó. Liên quan đến phiên và SessionFactory, tôi có một mô-đun cho biết: Thao
builder.Register(c => c.Resolve<ISessionFactory>().OpenSession())
.InstancePerMatchingLifetimeScope(WebLifetime.Request)
.OnActivated(e =>
{
e.Context.Resolve<TransactionManager>().CurrentTransaction = ((ISession)e.Instance).BeginTransaction();
});
builder.Register(c => ConfigureNHibernate())
.SingleInstance();
nơi ConfigureNHibernate(), trả về SessionFactory cơ sở, trông giống như:
private ISessionFactory ConfigureNHibernate()
{
Configuration cfg = new Configuration().Configure();
cfg.AddAssembly(typeof(Entity).Assembly);
return cfg.Configure().BuildSessionFactory();
}
Hiện nay, đây là giới hạn chỉ một cơ sở dữ liệu. Trong bất kỳ kịch bản NHIB nào khác, tôi có khả năng sẽ chuyển các phiên bản của SessionFactories riêng biệt thành một băm và truy xuất chúng khi cần thiết. Tôi không muốn phải thiết kế lại toàn bộ công việc vì chúng tôi khá gần với bản phát hành chính. Vì vậy, tôi đoán tôi cần phải sửa đổi ít nhất các phương pháp trên để tôi có thể cấu hình độc lập hai SessionFactories. Vùng màu xám của tôi là cách tôi sẽ đi về việc chỉ định Nhà máy chính xác được sử dụng với một kho lưu trữ cụ thể (hoặc ít nhất là đối với các thực thể cụ thể cho cơ sở dữ liệu thứ hai đó).
Bất kỳ ai có kinh nghiệm với tình huống này trong khi sử dụng vùng chứa IoC và NHibernate theo cách này?
EDIT Tôi đã stubbed ra một phương pháp GetSessionFactory mà phải mất một đường dẫn tập tin cấu hình, kiểm tra sự tồn tại của một SessionFactory khớp trong HttpRuntime.Cache, tạo ra một trường hợp mới nếu ta không tồn tại, và trả về SessionFactory đó. Bây giờ tôi vẫn cần phải búa ra làm thế nào để nói với Autofac như thế nào và khi nào để xác định một đường dẫn cấu hình thích hợp. Phương pháp mới trông giống như (mượn rất nhiều từ bài 2006 của Billy here):
private ISessionFactory GetSessionFactory(string sessionFactoryConfigPath)
{
Configuration cfg = null;
var sessionFactory = (ISessionFactory)HttpRuntime.Cache.Get(sessionFactoryConfigPath);
if (sessionFactory == null)
{
if (!File.Exists(sessionFactoryConfigPath))
throw new FileNotFoundException("The nhibernate configuration file at '" + sessionFactoryConfigPath + "' could not be found.");
cfg = new Configuration().Configure(sessionFactoryConfigPath);
sessionFactory = cfg.BuildSessionFactory();
if (sessionFactory == null)
{
throw new Exception("cfg.BuildSessionFactory() returned null.");
}
HttpRuntime.Cache.Add(sessionFactoryConfigPath, sessionFactory, null, DateTime.Now.AddDays(7), TimeSpan.Zero, System.Web.Caching.CacheItemPriority.High, null);
}
return sessionFactory;
}
Việc lưu trữ nhà máy trong bộ nhớ cache là một ý tưởng tồi. Nó không phải là thứ có thể biến mất và được tái tạo. –
Tôi biết. Trong thực tế, tôi sẽ phải quản lý tuổi thọ của đối tượng được lưu trữ đó. Ví dụ của Billy thực sự đã tiến thêm một bước nữa và tạo ra một lớp SessionManager có phạm vi singleton để xử lý các vấn đề về bộ nhớ đệm. Tôi đã cố gắng để câm nó xuống vì vậy tôi cuối cùng có thể cho phép Autofac quản lý nó thông qua cơ chế phạm vi riêng của nó (rất thanh lịch). – nkirkes