我希望将我的Entity Framework上下文绑定为每个NServicebus消息的作用域。下面的代码会成功吗?
Bind<IDbContext>().To<MyContext>()
.InScope(x => x.Kernel.Get<IBus>().CurrentMessageContext.Id);
背景
我有一个NServicebus服务,它有几个IMessageHandler,可以从MSMQ队列中读取IEvents。
每个处理程序转换消息并通过位于实体框架上下文的特定IRepository将其保存到MS SQL数据库。
使用NServicebus.ObjectBuilder.Ninject
通过ninject注入每个处理程序所需的存储库。public class Product
{
public string Code { get; set; }
public Category Category { get; set; }
}
public class Category
{
public string Code { get; set; }
}
public class SampleContext : IDbContext
{
IDbSet<Product> Products { get; }
IDbSet<Category> Categories{ get; }
}
public class ProductRepository : IProductRepository
{
private IDbContext _context;
public ProductRepository(IDbContext ctx) { _context = ctx; }
public void Add(Product p)
{
_context.Products.Add(p);
_context.SaveChanges();
}
}
public class CategoryRepository : ICategoryRepository
{
private IDbContext _context;
public CategoryRepository (IDbContext ctx) { _context = ctx; }
public Category GetByCode(string code)
{
return _context.Categories.FirstOrDefault(x => x.Code == code);
}
}
public class AddProductMessageHandler : IMessageHandler<IAddProductEvent>
{
private IProductRepository _products;
private ICategoryRepository _categories;
public AddProductMessageHandler(IProductRepository p, ICategoryRepository c)
{
_products = p;
_categories = c;
}
public void Handle(IAddProductEvent e)
{
var p = new Product();
p.Code = e.ProductCode;
p.Category = _categories.GetByCode(e.CategoryCode);
_products.Add(p);
}
}
问题
如果EF上下文绑定在Transient范围(默认)中,则处理程序中的每个绑定存储库都有自己的上下文实例。
Bind<IDbContext>().To<SampleContext>();
如果我从一个存储库加载一个对象然后通过另一个存储库保存它,则会导致问题。
同样,如果它绑定在Singleton范围内,那么所有存储库都会使用相同的上下文,但随后它会慢慢填满跟踪的更改并使我的所有ram上升(并且启动速度越来越慢)。
Bind<IDbContext>().To<SampleContext>().InSingletonScope();
问题
理想情况下,我希望每个消息处理程序都有1个EF上下文,所有需要的存储库(该处理程序)都用于加载和保存实体。
将上下文作为当前消息的范围确定Id属性是一种安全/可靠/良好的方法吗?
Bind<IDbContext>().To<SampleContext>()
.InScope(x => x.Kernel.Get<IBus>().CurrentMessageContext.Id);
答案 0 :(得分:2)
请参阅我的博客文章,其中介绍了除NSB 4.0之外的范围
http://www.planetgeek.ch/2013/01/16/nservicebus-unitofworkscope-with-ninject/
如果你有3.0,你可以查看当前的开发分支并将扩展方法移植到你的代码中。您只需要更改范围名称。
答案 1 :(得分:0)
我不熟悉EF背景,所以如果下面的答案没有任何意义,请不要理会。 p>
如果EF上下文类似于NH ISession,那么我认为更好的选择是使用与NH implementation相同的方式使用UoW。
您可以阅读有关UoW here的更多信息。