我正在开发一个 ASP.NET MVC 应用程序,我在其中使用 NHibernate 和 Ninject。
问题是由以下控制器引起的:
public class ShoppingCartController : Controller
{
private readonly Data.Infrastructure.IShoppingCartRepository _shoppingCartRepository;
private readonly Data.Infrastructure.IShopItemRepository _shopItemRepository;
public ShoppingCartController(Data.Infrastructure.IShoppingCartRepository shoppingCartController,
Data.Infrastructure.IShopItemRepository shopItemRepository)
{
_shoppingCartRepository = shoppingCartController;
_shopItemRepository = shopItemRepository;
}
public ActionResult AddToShoppingCart(FormCollection formCollection)
{
var cartItem = new Data.Models.ShoppingCartItem();
cartItem.ChangeDate = DateTime.Now;
cartItem.ShopItem = _shopItemRepository.GetShopItem(SessionData.Data.Info, Convert.ToInt32(formCollection["shopItemId"]));
//IF I DONT´T CALL THE METHOD ABOVE, AddToCart works
_shoppingCartRepository.AddToCart(SessionData.Data.Info, cartItem);
//BUT IF I CALL THE GetShopItem METHOD I GET THE EXCEPTION HERE!
return RedirectToAction("Index", "Shop");
}
}
我知道大多数时候这个异常是由错误的映射引起的,但我很确定我的映射是正确的,因为如果我不调用 GetShopItem,AddToCart 方法就可以工作......
所以这里是 ShopItemRepository 的代码:
public class ShopItemRepository : ReadOnlyRepository<ShopItem>, IShopItemRepository
{
public ShopItemRepository(IUnitOfWork uow) : base(uow)
{
}
public ShopItem GetShopItem(SessionParams param, int id)
{
return CurrentSession.QueryOver<ShopItem>()
.Where(x => x.ProcessId == param.ProcessId &&
x.CatalogueId == param.CatalogueId &&
x.Id == id)
.SingleOrDefault();
}
public IList<ShopItem> GetShopItems(SessionParams param)
{
return CurrentSession.GetNamedQuery("GetShopItems")
.SetParameter("requestor_id", param.RequestorId)
.SetParameter("recipient_id", param.RecipientId)
.SetParameter("process_id", param.ProcessId)
.SetParameter("catalogue_id", param.CatalogueId)
.List<ShopItem>();
}
}
最后是我的 UnitOfWork 的代码(基本上它只是 Session 的包装器,因为我不想在我的 MVC 项目中引用 NHibernate)
public class UnitOfWork : IUnitOfWork, IDisposable
{
private NHibernate.ISession _currentSession;
public NHibernate.ISession CurrentSession
{
get
{
if(_currentSession == null)
{
_currentSession = SessionFactoryWrapper.SessionFactory.OpenSession();
}
return _currentSession;
}
}
public void Dispose()
{
if(_currentSession != null)
{
_currentSession.Close();
_currentSession.Dispose();
_currentSession = null;
}
GC.SuppressFinalize(this);
}
}
附录:
我的 NinjectWebCommon 类
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
kernel.Bind<Data.Infrastructure.ICatalogueRepository>().To<Data.Repositories.CatalogueRepository>();
kernel.Bind<Data.Infrastructure.ICategoryRepository>().To<Data.Repositories.CategoryRepository>();
kernel.Bind<Data.Infrastructure.IContactRepository>().To<Data.Repositories.ContactRepository>();
kernel.Bind<Data.Infrastructure.IProcessRepository>().To<Data.Repositories.ProcessRepository>();
kernel.Bind<Data.Infrastructure.IShopItemRepository>().To<Data.Repositories.ShopItemRepository>();
kernel.Bind<Data.Infrastructure.IShoppingCartRepository>().To<Data.Repositories.ShoppingCartRepository>();
}
}
IUnitOfWork 设置为 RequestScope 因此在 ShoppingCartController 的情况下,两个存储库共享相同的 UOW 对吗?
也许这可能会导致问题?