我正在开发.NET 3.5,NHibernate并托管在Windows Azure上的ASP.NET MVC Web应用程序。什么时候,webapp从本地开发结构运行,它工作正常。但是,当我将其移动到Windows Azure时,从MVC Web角色执行的每个插入都会以下面列出的异常结束。
知道我的NHibernate逻辑有什么问题吗? (可能是会话管理,不确定)
[AssertionFailure:Lokad.Translate.Entities.User条目中的null id(发生异常后不刷新会话)] NHibernate.Event.Default.DefaultFlushEntityEventListener.CheckId(Object obj,IEntityPersister persister,Object id,EntityMode entityMode)+292 NHibernate.Event.Default.DefaultFlushEntityEventListener.GetValues(Object entity,EntityEntry entry,EntityMode entityMode,Boolean mightBeDirty,ISessionImplementor session)+93 NHibernate.Event.Default.DefaultFlushEntityEventListener.OnFlushEntity(FlushEntityEvent事件)+158 NHibernate.Event.Default.AbstractFlushingEventListener.FlushEntities(FlushEvent事件)+469 NHibernate.Event.Default.AbstractFlushingEventListener.FlushEverythingToExecutions(FlushEvent事件)+339 NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent事件)+85 NHibernate.Impl.SessionImpl.Flush()+ 275 NHibernate.Transaction.AdoTransaction.Commit()+236 Lokad.Translate.Repositories.PageRepository.Create(Page page) Lokad.Translate.Controllers.PagesController.Create(Page page) lambda_method(ExecutionScope,ControllerBase,Object [])+69 System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext,IDictionary
2 parameters) +251 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary
2个参数)+31 System.Web.Mvc。<> c__DisplayClassa.b__7()+88 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter过滤器,ActionExecutingContext preContext,Func1 continuation) +534 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList
1个过滤器,ActionDescriptor actionDescriptor,IDictionary`2参数)+312 System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext,String actionName)+856 System.Web.Mvc.Controller.ExecuteCore()+ 185 System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase httpContext)+221 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()+ 586 System.Web.HttpApplication.ExecuteStep(IExecutionStep step,Boolean& completedSynchronously)+177
请注意,我使用的是_session.FlushMode = FlushMode.Commit;
,User
用于自定义RoleProvider
public class SimpleRoleProvider : RoleProvider
{
readonly UserRepository Users = new UserRepository();
public override string[] GetRolesForUser(string username)
{
try
{
var user = Users.Get(username);
// no role if user is not registered
if (null == user) return new string[0];
// default role for registered user
return user.IsManager ? new[] { "Manager", "User" } : new[] { "User" };
}
catch (Exception)
{
// role should not fail in case of DB issue.
return new string[0];
}
}
}
答案 0 :(得分:18)
在NHibernate事务中,你永远不应该捕获异常并忽略它们。
我试着解释原因。
例如,可能存在由数据库中的约束引起的异常。 (它也可能是由映射问题,属性或其他任何东西引发的异常引起的。)NHibernate尝试将内存中的状态与数据库同步。这是在提交时完成的 - 有时在查询之前完成,以确保对实际数据进行查询。当此同步失败时,数据库中的状态是随机的,某些更改会保留,而其他更改则不会。在这种情况下,你唯一能做的就是关闭会话。
请考虑代码中的决策和计算基于内存中的值。但是 - 如果忽略异常,这个值不是数据库中的值,它们永远不会存在。因此,您的逻辑将决定并计算“幻想数据”。
顺便说一下,抓住任何异常(无类型)并忽略它们绝不是一个好主意。您应该始终知道您处理的例外情况,并确保可以继续。
你在这里做的是吞咽编程错误。相信我,系统将不会更稳定。问题仅在于:您是否注意到错误发生时,或者您是否忽略错误,甚至将错误结果持久保存到数据库?当你执行后者时,当数据库不一致时,你不必感到惊讶,当你试图从数据库中获取数据时会出现其他错误。而且你永远不会找到导致错误的实际原因的代码。
答案 1 :(得分:4)
我终于找到了解决自己问题的方法。如果人们有兴趣,我会在这里发布解决方案。
public class SimpleRoleProvider : RoleProvider
{
// isolated session management for the RoleProvider to avoid
// issues with automated management of session lifecycle.
public override string[] GetRolesForUser(string username)
{
using (var session = GlobalSetup.SessionFactory.OpenSession())
{
var users = new UserRepository(session);
var user = users.Get(username);
// no role if user is not registered
if (null == user) return new string[0];
// default role for registered user
return user.IsManager ? new[] {"Manager", "User"} : new[] {"User"};
}
}
}
基本上发生的事情是RoleProvider
存储库似乎与常规的in-view / in-controller存储库没有相同的生命周期。因此,在调用RoleProvider时,NHibernate会话已被处理,导致上面观察到异常。
我已在上面用以下内容替换了代码。这个有自己的NHibernate会话管理,最终工作正常。
答案 2 :(得分:0)
如果您的列名包含保留字(例如,使用状态作为列名并且无法保存),则会发生此异常。