nHibernate,我的对象得到了保存,但为什么呢?

时间:2011-03-22 14:16:30

标签: nhibernate asp.net-mvc-3 fluent-nhibernate

不要误解我的意思,我希望他们得到保存。但我一直以为我必须致电Session.SaveOrUpdate(x);去做。但这是正在发生的事情。

基本问题

  

尽管我从未调用过保存方法,但对象仍然被“保存”。

详细

对象通过Fluent nHibernate映射,这里没什么特别的。

我将ISessionFactoryISession映射到Ninject ASP.NET MVC,就像这样。

        Bind<ISessionFactory>()
            .ToMethod(c => CreateSessionFactory())
            .InSingletonScope();

        Bind<ISession>()
            .ToMethod(c => OpenSession())
            .InRequestScope()
            .OnActivation(session =>
            {
                System.Diagnostics.Debug.WriteLine("Creating Session");
                session.BeginTransaction();
                session.FlushMode = FlushMode.Commit;
            })
            .OnDeactivation(session =>
            {
                if (session.Transaction.IsActive)
                {
                    try
                    {
                        System.Diagnostics.Debug.WriteLine("Disposing Session");

                        session.Transaction.Commit();
                    }
                    catch
                    {
                        session.Transaction.Rollback();
                    }
                }
            });

然后,当我想要执行某些操作时,我在域类上有一个简单的方法,或者扩展方法(只是因为它更容易组织),就像这样。

class Member {
  public virtual int Id { get; set; }
  public virtual string Email { get; set; }
  public virtual string Password { get; set; }
}

然后,我在一些延伸方法中加入风味..

using System;
using System.Linq;

namespace System.Linq
{
    public static class  MembershipExtensions
    {
        public static void ChangePassword(this Membership.Member member, string password)
        {
            member.Password = System.Security.Cryptography.Hashing.ComputeHash(password, "SHA512", null);
        }

        public static bool VerifyPassword(this Membership.Member member, string password)
        {
            return System.Security.Cryptography.Hashing.VerifyHash(password, "SHA512", member.Password);
        }
    }
}

到目前为止,在Ooo的土地上一切都很好。现在这里的东西变得很糟糕。

    [HttpPost]
    public ActionResult Password(ViewModels.MemberEditPasswordViewModel model)
    {
        if (ModelState.IsValid)
        {
            // attempt to perform the password change on the current member. 
            var member = User.AsMember(); // retrieve the current user

            if (member.VerifyPassword(model.Current)) // verify the current password
                member.ChangePassword(model.Password);

            //if (Bus.Update(member) != null) {
            //    return RedirectToAction("Index", "Home");
            //}
            //else {
            //    ModelState.AddModelError("", "The original password is incorrect.");
            //}
        }

        // If we got this far, something failed, redisplay the form
        // with the errors listed and give them a chance to try again.
        return View(model);
    }

这是疯狂的部分。 此作品。注意什么是这么奇怪?我从不对SaveOrUpdate对象调用任何Member种类。我评论了我的Update代码只是为了测试它。

附加数据

  

这是可能与问题相关的信息,但我不想用额外的代码来阻止所有事情。

对于那些寻找我的AsMember()方法的人来说,这里也是如此。我想尽我所能提供所有数据。我喜欢这种行为,但我不确定这是正常还是正确......

using System;
using System.Linq;
using System.Linq.Expressions;

namespace System.Web.Mvc
{
    public static class MembershipProviderExtensions
    {
        public static Membership.Member AsMember(this System.Security.Principal.IPrincipal user)
        {
            // if the user is not authenticated, then we should
            // not have made it this far, and error out gracefully.
            if (!user.Identity.IsAuthenticated)
                return null;

            // get the service bus from the locator
            var bus = DependencyResolver.Current.
                GetService<IServiceBus>();

            // return the queried result
            return bus.Request<Membership.Queries.CurrentMember>(user);
        }
    }
}

当前成员只需通过查询对象获取,发送到IServiceBus。 (这是一个自定义服务总线,而不是一个开源项目)。

/// <summary>
/// Resolves the currently authenticated <see cref="Member"/>.
/// </summary>
public class CurrentMember : IRequestFor<System.Security.Principal.IPrincipal, Member>
{
    private readonly ISession session;

    public CurrentMember(ISession session) {
        this.session = session;
    }

    public Member Reply(System.Security.Principal.IPrincipal Model)
    {
        // if the user is not authenticated, then we should
        // not have made it this far, and error out gracefully.
        if (!Model.Identity.IsAuthenticated)
            return null;

        return session.Query<Member>()
            .Where(context => context.Email == Model.Identity.Name)
            .Take(1)
            .SingleOrDefault();
    }
}

以下是Request<T>实施..

    public dynamic Request<T>(dynamic message)
    {
        dynamic implementation = kernel.Get<T>();
        return implementation.Reply(message);
    }

2 个答案:

答案 0 :(得分:2)

您应该将会话设置为FlushAction.Never

使用会话加载的对象将在一次性使用时刷新。

此外,还有奖励性能提升,因为会话不需要检查所有加载对象的状态。 这在加载大量数据的情况下非常重要。

答案 1 :(得分:1)

我注意到对象是隐式保存在Flush或Commit(?)上的。当我在我的类中有一个像int这样的非可空类型并且在数据库中可以为空时,这种行为总是会出现(在我的情况下)。 get拉出一个null,初始化为0,然后我得到一个隐式更新而不调用该类的save或update,因为实体已经改变了。