我刚开始考虑在我的一个应用程序中使用NHibernate二级缓存.我可能会使用NHibernate.Caches.SysCache.SysCacheProvider
依赖于ASP.net缓存的.
启用缓存不是问题,但我想知道如何管理缓存,例如以编程方式从缓存中删除某些实体等.
我的应用程序是某种图像数据库.用户通过后端上传图像,并可以通过访问在前端查看图像/ImageDb/Show?userId=someUserId
数据不会经常变化.如果它发生变化,用户在后端的名为"清除我的缓存"的按钮无关紧要,该按钮会从缓存中删除此用户的缓存对象.
我在网上找到了一个可以从nhibernates二级缓存中删除所有缓存对象的解决方案.但这对我来说有点太暴力了......我不想为几十个用户清除整个缓存,因为一个用户试图清除缓存中的自己的数据.
所以我基本上想做的是:有选择地从C#中的nhibernates二级缓存中删除缓存的db对象.
这可能吗?我想这也取决于缓存提供商.如果ASP.net缓存提供程序无法做到这一点,我可以使用其他内置/开源建议.
我正在迁移这样的应用程序:
Vehicle v = null;
using (ISession session = MyNHibernateSession())
{
v = Vehicle.FindById(1);
}
using (ISession session = MyNHibernateSession())
{
// somwwhere into these4 lines Vehicle comes Finded
DoSomething();
DoSomething2();
DoSomething3();
DoSomething4();
DoSomething5();
DoSomething6();
// if i do this i get an error "another object with the same id etc etc etc
session.Update(v);
}
Run Code Online (Sandbox Code Playgroud)
我不想做这样的事情:
session.EvictAllByType(typeof(Vehicle));
Run Code Online (Sandbox Code Playgroud)
可能吗?怎么样?谢谢
使用工作单元/存储库模式构建了一个小应用程序后,我很难理解如何在我的业务层中正确使用它.我的应用程序有一个数据访问层,可以是NHibernate或实体框架.我可以轻松地在这些之间切换.
我有许多存储库,例如,客户,订单等.我的工作单元将是一个ISession或一个对象上下文,具体取决于我想要测试的DAL.
我的业务层包含一个业务方法 - CreateOrder().我正在努力理解的是,在业务层中我应该初始化我的工作单元和我的存储库.
专注于Nhibernate,我的DAL看起来像:
public class NHibernateDAL : IUnitOfWork
{
log4net.ILog log = log4net.LogManager.GetLogger(typeof(NHibernateDAL));
ISession context;
public NHibernateDAL()
{
context = SessionProvider.OpenSession();
this.Context.BeginTransaction();
CurrentSessionContext.Bind(context);
}
public ISession Context
{
get { return context; }
}
public void Commit()
{
this.Context.Transaction.Commit();
context.Close();
}
public void Dispose()
{
ISession session = CurrentSessionContext.Unbind(SessionProvider.SessionFactory);
session.Close();
}
}
Run Code Online (Sandbox Code Playgroud)
在我的业务层中,我想知道我应该在哪里声明我的工作单元和存储库.它们是在类级别还是在CreateOrder方法中声明的?
例如:
public class BusinessLogic
{
UnitOfWork _unitOfWork = new UnitOfWork(NHibernateDAL);
NhRepository<Order> _orderRepository = new NhRepository<Order>(_unitOfWork);
NhRepository<Customer> _customerRepository = new NhRepository<Customer>(_unitOfWork);
....
public void CreateOrder(.....) …
Run Code Online (Sandbox Code Playgroud) 我已经尝试了三天用Castle和wcf弄清楚这个NHibernatefacility的事情,它真的让人很沮丧.
在解决了十几个错误之后,我来到了这个看起来非常明显但我无法解决的问题.
这是我的global.asax的Application_Start
container.AddFacility<AutoTxFacility>();
container.Register(Component.For<INHibernateInstaller>().ImplementedBy<NHibernateInstaller>());
container.AddFacility<NHibernateFacility>();
container.AddFacility<WcfFacility>();
container.Register(
Component.For<IAuthService>().ImplementedBy<AuthService>().LifestylePerWcfOperation(),
Component.For<IUserRepository>().ImplementedBy<UserRepository>().LifestylePerWcfOperation(),
Component.For<IActionWebService>().ImplementedBy<ActionWebService>().Named("ActionWebService").LifestylePerWcfOperation(),
Component.For<ISession>().LifeStyle.PerWcfOperation().UsingFactoryMethod(x => container.Resolve<ISessionManager>().OpenSession()));
Run Code Online (Sandbox Code Playgroud)
这适用于第一个请求.之后,它出现了这个错误.
工厂处理完毕,无法再使用.对象名称:'this'.
错误发生在我的userrepository中
[Transaction]
public virtual User GetUserByCredentials(string email, string password)
{
using (var tx = session())
{
return tx.QueryOver<User>().Where(x => x.Email == email && x.Password == password).SingleOrDefault();
}
}
Run Code Online (Sandbox Code Playgroud)
我感觉这与LIfestyle有关.我尝试了多种组合但不成功.我不知道该做什么.我进入这个城堡的东西有所有的设施(应该让生活更轻松),由于缺乏文件,它真的很复杂.我无法找到一个下降指南来实现所有这些,更不用说一些不是4年的东西了.
请帮忙!
NHibernate的ISession公开了一个带有两个重载的方法Persist().我无法在任何地方找到有关此方法的文档.在http://nhibernate.info/doc/nh/en/index.html上的NHibernate参考资料中甚至没有提到它.
这种方法是否已弃用,还是会被弃用?什么时候应该使用?它与SaveOrUpdate()相比如何?
任何指针都将非常感激.
我正在使用NHibernate创建大量实体,将它们附加到我的ISession,然后使用事务将我的更改提交到数据库.代码示例如下:
ISession _context = SessionProvider.OpenSession();
//Create new entities
for(int i=0; i<100; i++)
{
MyEntity entity = new MyEntity(i);
//Attach new entity to the context
_context.Save(entity);
}
//Persist all changes to the database
using(var tx = _context.BeginTransaction())
{
//Flush the session
tx.Commit();
}
Run Code Online (Sandbox Code Playgroud)
我的印象是_context.Save()行只是让ISession知道新实体,但是在我通过tx.Commit()行刷新会话之前,没有任何更改持久存储到数据库.
我观察到的是,每次调用_context.Save()时数据库都会获得一个新实体.因此,我最终会对数据库进行过多的单独调用.
有谁知道为什么ISession.Save()会自动持久更改?我是否误解了NHibernate的行为方式?谢谢.
***编辑 - 只是为了澄清(根据两个建议的答案) - 我的问题是,一旦我调用_context.Save(),数据库就会更新.我不指望这会发生.我希望在调用tx.Commit()之前不要将任何内容插入到数据库中.到目前为止,两个建议的答案都没有帮助解决这个问题.
可在此处找到有关身份生成器的一些有用信息
我在 ASP.NET MVC 应用程序中将 Castle Windsor 与 NHIbernate 一起用于 IoC。它运行良好,注册如下(有一个例外):
container.Register(Component.For<ISessionFactoryBuilder.().ImplementedBy<SessionFactoryBuilder>().LifestyleSingleton());
// Register the NHibernate session factory as a singleton using custom SessionFactoryBuilder.BuildSessionFactory method.
container.Register(Component.For<ISessionFactory>().UsingFactoryMethod(k => k.Resolve<ISessionFactoryBuilder>().BuildSessionFactory("ApplicationServices")).LifestyleSingleton());
container.Register(Component.For<IInterceptor>().ImplementedBy<ChangeAuditInfoInterceptor>().LifestylePerWebRequest());
container.Register(Component.For<ISession>().UsingFactoryMethod(k => k.Resolve<ISessionFactory>()
.OpenSession(container.Resolve<IInterceptor>())).LifestylePerWebRequest());
Run Code Online (Sandbox Code Playgroud)
一切都很好,除了我的 ChangeAuditInterceptor 依次注入了 IAccountSession 服务,而 IAccountSession 服务又注入了 NHibernate ISession...这会导致以下循环依赖异常:
尝试解析组件“后期绑定 NHibernate.ISession”时检测到依赖循环。导致循环的解析树如下: 组件“后期绑定 NHibernate.ISession”解析为组件“Blah.Core.Services.AccountSession”的依赖项解析为组件“Blah.Core.Infrastruct.Data.ChangeAuditInfoInterceptor”的依赖项解析为组件“Blah.Core.Infrastruct.Installers.SessionFactoryBuilder”的依赖项 解析为组件“后期绑定 NHibernate.ISessionFactory”的依赖项 解析为组件“后期绑定 NHibernate.ISession”的依赖项,该组件是正在解析的根组件。
在过去的几年里,我通常使用 NHibernateSessionManager 来运行,它负责处理 IInterceptor 中的插入,而不会导致这种循环依赖问题(与使用 Castle Windsor 的 usingFactoryMethod 功能的 SessionFactoryBuilder 的这种用法相反)。
关于如何解决这种循环依赖有什么建议吗?还没有开始通过其他方式侵入 AccountSession 的 ISession(即绕过问题并因此产生气味的属性注入)。我已将 AccountSession 服务的 ISession 注入切换为属性注入,并且工作正常,但我不喜欢隐式契约与构造函数显式契约。
public class AccountSession : IAccountSession
{
private readonly ISession _session;
public …
Run Code Online (Sandbox Code Playgroud) 在这个问题中,用户要求更好的方法来关闭会话,因为他遇到了一些错误.
投票最多的回答是Ayende的回答:
你应该总是使用session.Dispose(); 另一个是非常奇怪的事情
我应该一直打电话session.Dispose()
吗?还不够打电话session.Close()
?
isession ×8
nhibernate ×7
c# ×1
caching ×1
layer ×1
repository ×1
session ×1
transactions ×1
unit-of-work ×1
wcf ×1