nHibernate, мои объекты сохраняются, но почему? - PullRequest
0 голосов
/ 22 марта 2011

Не поймите меня неправильно, я хочу чтобы их спасли.Но я всегда думал, что должен позвонить Session.SaveOrUpdate(x);, чтобы сделать это.Но вот что происходит.

Основной вопрос

Объекты «сохраняются», несмотря на то, что я никогда не вызывал метод сохранения.

Подробности

Объекты отображаются через Fluent nHibernate, здесь ничего особенного.

Я сопоставляю свои ISessionFactory и ISession - 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);
        }
    }
}

Пока все хорошо на земле Ооо.Теперь вот где вещи становятся неуместными.

    [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 ]

2 голосов
/ 22 марта 2011

Вы должны установить сеанс на FlushAction.Never

Объекты, загруженные с помощью сеанса, будут очищаться от одноразовых.

Кроме того, повышается бонусная производительность, так как сеанс не должен проверять состояние всех загруженных объектов. Это важно в тех случаях, когда загружается много данных.

1 голос
/ 22 марта 2011

Я заметил, что объекты сохраняются в Flush или Commit (?) Неявно. Такое поведение всегда поднимает голову (в моем случае), когда у меня есть тип, не допускающий значения NULL, например, int в моем классе и Nullable в базе данных. Метод get вытягивает нулевое значение, которое инициализируется значением 0, а затем я получаю неявное обновление без вызова сохранения или обновления для этого класса, поскольку объект изменился.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...