gpt4 book ai didi

asp.net-mvc - 什么会导致 NHibernate 的 Save 方法无提示地失败?

转载 作者:行者123 更新时间:2023-12-02 03:32:45 24 4
gpt4 key购买 nike

我的任务是接管现有的 ASP.NET MVC 2.0 Web 应用程序,该应用程序是由不再提供任何帮助的第三方开发人员开发的。需要向项目添加一些功能,这需要将项目升级到 .NET 4.5,该升级已执行。

MSSQL 2008 R2 数据库访问的基础站点已使用 NHibernate 版本 2.0.1.4000 以及 CaSTLe 和 FluentNHibernate 实现。

这是我参与的第一个使用NHibernate的项目,我遇到了一个让我难住的问题。直到升级到 .NET 4.5 后,该问题才出现。

除一个数据库操作外,所有数据库操作均正常运行。保存特定对象(Opportunity 类型)到数据库(此对象直接映射到 Opportunity 数据库表)失败。在保存之前(在本例中是 SQL UPDATE 语句),对象已设置新值。但数据库中的记录保存后始终是旧值。

连接log4net查看调试代码,显示记录确实已更新,但在UPDATE语句中使用旧值。

令人惊讶的是,Opportunity 对象最初是使用相同的 Save 方法(尽管通过不同的操作方法)保存的,并且可以很好地保存到数据库。

所以我的问题是,什么会导致这种情况发生?由于我不是NHibernate专家,NHibernate版本是否与.NET 4.5根本不兼容?或者任何人都可以提供有关问题可能是什么的指示吗?我很高兴展示任何代码,但由于代码太多,我需要知道什么。下面是一个入门:

Global.asax 有以下对 NHibernate 的引用:

private static void MvcApplication_BeginRequest(object sender, System.EventArgs e)
{
NHibernateSessionManager.Instance.BeginTransaction();
}

private static void MvcApplication_EndRequest(object sender, System.EventArgs e)
{
NHibernateSessionManager.Instance.CommitTransaction();
}

NHibernateSessionManager 类定义为(Opportunity 派生自 DomainBase):

public sealed class NHibernateSessionManager
{
private ISessionFactory sessionFactory;
private Configuration config;

#region Thread-safe, lazy Singleton

public static NHibernateSessionManager Instance
{
get
{
return Nested.nHibernateSessionManager;
}
}

private NHibernateSessionManager()
{
InitSessionFactory();
}

private class Nested
{
internal static readonly NHibernateSessionManager nHibernateSessionManager = new NHibernateSessionManager();
}

#endregion


private void InitSessionFactory()
{
var autoMappings = AutoPersistenceModel.MapEntitiesFromAssemblyOf<DomainBase>()
.Where(type =>
typeof(DomainBase).IsAssignableFrom(type) &&
type.IsClass &&
!type.IsAbstract)
.WithSetup(s =>
{
s.IsBaseType = type =>
type == typeof (DomainBase);
})
.UseOverridesFromAssemblyOf<OpportunityMappingOverride>()
.ConventionDiscovery.Add(DefaultLazy.AlwaysTrue())
.ConventionDiscovery.Add<CascadeAllHasOneConvention>()
.ConventionDiscovery.Add<CascadeAllHasManyConvention>()
.ConventionDiscovery.Add<CascadeAllReferenceConvention>();

sessionFactory = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005
.ConnectionString(c => c.FromConnectionStringWithKey("Default"))
.UseReflectionOptimizer()
.Cache(c => c.UseQueryCache().UseMininmalPuts().ProviderClass<SysCacheProvider>())
.ShowSql())
.Mappings(m => m.AutoMappings.Add(autoMappings))
.ExposeConfiguration(SetConfiguration)
.BuildSessionFactory();
}

private void SetConfiguration(Configuration cfg)
{
config = cfg;
}

public void RegisterInterceptor(IInterceptor interceptor)
{
ISession session = threadSession;

if (session != null && session.IsOpen)
{
throw new CacheException("You cannot register an interceptor once a Session has already been opened");
}

GetSession(interceptor);
}

public void GenerateSchema()
{
new SchemaExport(config).Execute(false, true, false, false);
}

public ISession GetSession()
{
return GetSession(null);
}

private ISession GetSession(IInterceptor interceptor)
{
ISession session = threadSession;

if (session == null)
{
if (interceptor != null)
{
session = sessionFactory.OpenSession(interceptor);
}
else
{
session = sessionFactory.OpenSession();
}

threadSession = session;
}

return session;
}

public void CloseSession()
{
ISession session = threadSession;
threadSession = null;

if (session != null && session.IsOpen)
{
session.Close();
}
}

public void BeginTransaction()
{
ITransaction transaction = threadTransaction;

if (transaction == null)
{
transaction = GetSession().BeginTransaction();
threadTransaction = transaction;
}
}

public void CommitTransaction()
{
ITransaction transaction = threadTransaction;

try
{
if (transaction != null && !transaction.WasCommitted && !transaction.WasRolledBack)
{
transaction.Commit();
threadTransaction = null;
}
}
catch (HibernateException)
{
RollbackTransaction();
throw;
}
}

public void RollbackTransaction()
{
ITransaction transaction = threadTransaction;

try
{
threadTransaction = null;

if (transaction != null && !transaction.WasCommitted && !transaction.WasRolledBack)
{
transaction.Rollback();
}
}
finally
{
CloseSession();
}
}

private static ITransaction threadTransaction
{
get
{
return (ITransaction)CallContext.GetData("THREAD_TRANSACTION");
}
set
{
CallContext.SetData("THREAD_TRANSACTION", value);
}
}

private static ISession threadSession
{
get
{
return (ISession)CallContext.GetData("THREAD_SESSION");
}
set
{
CallContext.SetData("THREAD_SESSION", value);
}
}
}

我希望我不会因为这个问题太笼统而被拒绝。我花了一天时间试图弄清楚发生了什么,包括在网上进行大量搜索。

最佳答案

事实证明,问题在于 NHibernateSessionManager 类将其 ITransactionISession 对象存储在 System.Runtime.Remoting 中.Messaging.CallContext.

将其交换出来以将对象存储在 HttpContext.Current.Items 集合中解决了该问题。

我找到了this post这意味着 .NET 4.5 处理 CallContext 的方式与以前的版本相比略有不同,这显然导致了我的问题。

由于 NHibernateSessionManager 类位于一个类库中,该类库也被几个很少使用的控制台应用程序使用,因此我将回退到 CallContext 对象,如下所示(不太漂亮,可能有更好的选择,但对我有用[需要测试],因为我花了很长时间使用远程调试来解决这个问题):

    private static ITransaction threadTransaction
{
get
{
try
{
return (ITransaction)System.Web.HttpContext.Current.Items["THREAD_TRANSACTION"];
}
catch
{
return (ITransaction)CallContext.GetData("THREAD_TRANSACTION");
}
}
set
{
try
{
System.Web.HttpContext.Current.Items["THREAD_TRANSACTION"] = value;
}
catch
{
CallContext.SetData("THREAD_TRANSACTION", value);
}
}
}

private static ISession threadSession
{
get
{
try
{
return (ISession)System.Web.HttpContext.Current.Items["THREAD_SESSION"];
}
catch
{
return (ISession)CallContext.GetData("THREAD_SESSION");
}
}
set
{
try
{
System.Web.HttpContext.Current.Items["THREAD_SESSION"] = value;
}
catch
{
CallContext.SetData("THREAD_SESSION", value);
}
}
}

关于asp.net-mvc - 什么会导致 NHibernate 的 Save 方法无提示地失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27451558/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com