C# 刷新时返回旧数据
我正在使用TransactionScope和nHibernate。为了处理嵌套事务,我与TransactionScope一起创建了一个助手类。我的会话工厂:C# 刷新时返回旧数据,c#,asp.net-mvc,nhibernate,asp.net-core-mvc,C#,Asp.net Mvc,Nhibernate,Asp.net Core Mvc,我正在使用TransactionScope和nHibernate。为了处理嵌套事务,我与TransactionScope一起创建了一个助手类。我的会话工厂: public class SessionFactory { [ThreadStatic] private static ISessionFactory iSessionFactory; [ThreadStatic] protected static ISession
public class SessionFactory
{
[ThreadStatic]
private static ISessionFactory iSessionFactory;
[ThreadStatic]
protected static ISession session;
private static object syncRoot = new Object();
private static void buildSessionFactory()
{
lock (syncRoot)
{
if (session == null)
{
if (iSessionFactory == null)
{
Configuration configuration = new Configuration().Configure("hibernate.cfg.xml");
Assembly assembly = Assembly.GetCallingAssembly();
iSessionFactory = configuration.BuildSessionFactory();
}
if (session != null && session.IsOpen)
session.Dispose();
CurrentSessionContext.Bind(iSessionFactory.OpenSession());
session = iSessionFactory.OpenSession();
}
}
}
public static ISession OpenSession
{
get
{
if (session == null || !session.IsOpen)
{
session = null;
buildSessionFactory();
}
return session;
}
}
}
public class TransactionScopeHelper : SessionFactory, iTransactionScopeHelper
{
public static int count = 0;
public TransactionScope getTransactionScope()
{
if (count == 0)
{
if (session != null)
session.Clear();
}
count++;
return new TransactionScope(TransactionScopeOption.Required);
}
public void complete(TransactionScope tx)
{
count--;
if (count == 0)
{
session.Flush();
session = null;
}
tx.Complete();
}
public void rollbackTransaction()
{
count = 0;
session = null;
}
}
public T getById(long id)
{
ISession session = SessionFactory.OpenSession;
return session.Get<T>(id);
}
配置文件名为hibernate.cfg.xml,它是:
<configuration>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.driver_class">
NHibernate.Driver.MySqlDataDriver
</property>
<property name="dialect">NHibernate.Dialect.MySQL55InnoDBDialect</property>
<property name="connection.connection_string">connection string here</property>
<property name="current_session_context_class">thread_static</property>
<property name="show_sql">true</property>
<property name="generate_statistics">true</property>
<mapping assembly="assembly name here"/>
<!-- Here -->
</session-factory>
</hibernate-configuration>
<system.transactions>
<machineSettings maxTimeout="00:00:60" />
</system.transactions>
</configuration>
助手类仅在服务中使用,而不在存储库中使用
在服务中使用帮助器的示例:
public void updateCategory(CategoryDto category_dto)
{
try
{
using (TransactionScope tx = transactionScopeHelper.getTransactionScope())
{
//works here
transactionScopeHelper.complete(tx);
}
}
catch(Exception)
{
transactionScopeHelper.rollbackTransaction();
throw;
}
}
存储库中的函数示例:
public class SessionFactory
{
[ThreadStatic]
private static ISessionFactory iSessionFactory;
[ThreadStatic]
protected static ISession session;
private static object syncRoot = new Object();
private static void buildSessionFactory()
{
lock (syncRoot)
{
if (session == null)
{
if (iSessionFactory == null)
{
Configuration configuration = new Configuration().Configure("hibernate.cfg.xml");
Assembly assembly = Assembly.GetCallingAssembly();
iSessionFactory = configuration.BuildSessionFactory();
}
if (session != null && session.IsOpen)
session.Dispose();
CurrentSessionContext.Bind(iSessionFactory.OpenSession());
session = iSessionFactory.OpenSession();
}
}
}
public static ISession OpenSession
{
get
{
if (session == null || !session.IsOpen)
{
session = null;
buildSessionFactory();
}
return session;
}
}
}
public class TransactionScopeHelper : SessionFactory, iTransactionScopeHelper
{
public static int count = 0;
public TransactionScope getTransactionScope()
{
if (count == 0)
{
if (session != null)
session.Clear();
}
count++;
return new TransactionScope(TransactionScopeOption.Required);
}
public void complete(TransactionScope tx)
{
count--;
if (count == 0)
{
session.Flush();
session = null;
}
tx.Complete();
}
public void rollbackTransaction()
{
count = 0;
session = null;
}
}
public T getById(long id)
{
ISession session = SessionFactory.OpenSession;
return session.Get<T>(id);
}
public T getById(长id)
{
ISession session=SessionFactory.OpenSession;
返回会话.Get(id);
}
每当我更新某个实体时,在几次刷新后会显示旧数据,在一些刷新后会再次检索新数据。这几乎是连续的。为什么我会遇到这个问题?任何帮助都将不胜感激。这里发生了太多“不寻常”的事情,我几乎不知道从哪里开始
SessionFactory
NHibernate的会话工厂通常在应用程序启动时(或在第一次需要时)初始化一次,然后该实例将在程序期间有效,并在所有线程之间共享。我们通常不希望每个线程都有一个单独的实例(就像ThreadStatic那样)。反复初始化它将是一个严重的性能损失
如果存在会话,buildSessionFactory()将处理该会话,但除非会话为null,否则它将无法访问该代码,因此我不理解这里的真正意图
在buildSessionFactory()的末尾,iSessionFactory.OpenSession()被调用两次!一次就够了
您正在配置文件中设置当前会话上下文类,并调用CurrentSessionContext.Bind()。因此,您不需要维护自己的线程静态会话变量。这就是CurrentSessionContext的用途
最终必须处理会话。因此,调用名为likeOpenSession
的方法意味着我们将获得一个负责关闭的新会话。但是您自己的OpenSession()可以多次返回同一个会话,因此很难理解到底是谁负责关闭它。最好将其命名为CurrentSession
或类似名称
TransactionScopeHelper
这也是不可能理解的。存在对变量会话的引用,但未显示此变量的定义和设置。代码不完整。在某些情况下,会话引用被设置为null,但没有尝试对其进行处理,这是必需的
在会话上调用Clear()将从会话中删除所有状态,并使NHibernate无法跟踪所有加载的对象,因此无法执行脏检查并自动持久化。其他代码需要记住小心地重新添加所有内容
代码不显示实际创建会话、事务和事务范围的方式和时间。无法判断交互是否正确。会话是否知道事务范围
最后,回答你的问题:“为什么我会遇到这个问题?”
很抱歉,整个情况看起来一团糟。混乱的代码等于混乱的结果。当然,除非我上面提到的问题是由于部分拷贝粘贴遗漏了重要部分造成的。这里有太多“不寻常”的东西,我几乎不知道从哪里开始
SessionFactory
NHibernate的会话工厂通常在应用程序启动时(或在第一次需要时)初始化一次,然后该实例将在程序期间有效,并在所有线程之间共享。我们通常不希望每个线程都有一个单独的实例(就像ThreadStatic那样)。反复初始化它将是一个严重的性能损失
如果存在会话,buildSessionFactory()将处理该会话,但除非会话为null,否则它将无法访问该代码,因此我不理解这里的真正意图
在buildSessionFactory()的末尾,iSessionFactory.OpenSession()被调用两次!一次就够了
您正在配置文件中设置当前会话上下文类,并调用CurrentSessionContext.Bind()。因此,您不需要维护自己的线程静态会话变量。这就是CurrentSessionContext的用途
最终必须处理会话。因此,调用名为likeOpenSession
的方法意味着我们将获得一个负责关闭的新会话。但是您自己的OpenSession()可以多次返回同一个会话,因此很难理解到底是谁负责关闭它。最好将其命名为CurrentSession
或类似名称
TransactionScopeHelper
这也是不可能理解的。存在对变量会话的引用,但未显示此变量的定义和设置。代码不完整。在某些情况下,会话引用被设置为null,但没有尝试对其进行处理,这是必需的
在会话上调用Clear()将从会话中删除所有状态,并使NHibernate无法跟踪所有加载的对象,因此无法执行脏检查并自动持久化。其他代码需要记住小心地重新添加所有内容
代码不显示实际创建会话、事务和事务范围的方式和时间。无法判断交互是否正确。会话是否知道事务范围
最后,回答你的问题:“为什么我会遇到这个问题?”
很抱歉,整个情况看起来一团糟。混乱的代码等于混乱的结果。当然,除非我上面提到的问题是由于剩下的部分拷贝粘贴造成的