проблема икритерии - PullRequest
       18

проблема икритерии

0 голосов
/ 24 июня 2011

Я переопределяю метод репозитория с острой архитектурой, подобный этому:

public class UserRepository : NHibernateRepository<User>, IUserRepository
{
    public override User SaveOrUpdate(User entity)
    {
        ICriteria Criteria = Session.CreateCriteria(typeof(User));
        Criteria.Add(Expression.Eq("Email", entity.Email));
        User User = Criteria.UniqueResult<User>();

        if (User != null)
        {
        if (User.Id != entity.Id)
        {
            throw new ArgumentException("Please use a unique email address.");
        }
        }

        return base.SaveOrUpdate(entity);
    }
}

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

Может кто-то понять, почему это так? Так не должно быть, не так ли? Должно быть, я упускаю из виду нечто кровоточащее очевидное ...

Спасибо.

Christian

PS:

Это более полный код:

namespace x.Domain.Contracts.Repositories
{
    using SharpArch.Domain.PersistenceSupport;
    using SharpArch.NHibernate.Contracts.Repositories;

    public interface IUserRepository : INHibernateRepository<User>
    {
    }
}

namespace x.Tasks.Repositories
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Domain;
    using Domain.Contracts.Tasks;
    using Domain.Contracts.Repositories;
    using SharpArch.NHibernate;
    using NHibernate;
    using NHibernate.Criterion;

    public class UserRepository : NHibernateRepository<User>, IUserRepository
    {
        public override User SaveOrUpdate(User entity)
        {
            ICriteria Criteria = Session.CreateCriteria(typeof(User));
            Criteria.Add(Expression.Eq("Email", entity.Email));
            User User = Criteria.UniqueResult<User>();

            if (User != null)
            {
                if (User.Id != entity.Id)
                {
                    throw new ArgumentException("Please use a unique email address.");
                }
            }

            return base.SaveOrUpdate(entity);
        }
    }
}

namespace x.Tasks
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Domain;
    using Domain.Contracts.Tasks;
    using SharpArch.NHibernate.Contracts.Repositories;
    using NHibernate.Criterion;
    using NHibernate;
    using x.Web.Mvc.Controllers.ViewModels;
    using SharpArch.NHibernate.Web.Mvc;
    using x.Domain.Contracts.Repositories;

    public class UserTasks : IUserTasks
    {
        private readonly IUserRepository UserRepository;

        public UserTasks(IUserRepository UserRepository)
        {
            this.UserRepository = UserRepository;
        }

        [Transaction]
        public void CreateUser(CreateUserViewModel CreateUserViewModel)
        {
            User User = new User();
            User.ForeName = CreateUserViewModel.ForeName;
            User.LastName = CreateUserViewModel.LastName;
            User.Email = CreateUserViewModel.Email;
            User.Password = CreateUserViewModel.getSHA512PW(CreateUserViewModel.Password1);

            UserRepository.SaveOrUpdate(User);
        }
    }
}

Даже если я прокомментирую бит ICriteria, сущность даже не сохранится (несмотря на атрибут транзакции). Есть идеи?

PPS:

Еще некоторые детали плюс трассировка стека:

{"запрос не дал уникальный результат: 7"}

в NHibernate.Impl.AbstractQueryImpl.UniqueElement (список IList) в NHibernate.Impl.CriteriaImpl.UniqueResult () в NHibernate.Impl.CriteriaImpl.UniqueResultT в EID2.Tasks.Repositories.UserRepository.SaveOrUpdate (сущность пользователя) в C: \ Users \ csetzkorn \ Documents \ Visual Studio 2010 \ Projects \ EID2 \ Solutions \ EID2.Tasks \ Repositories \ UserRepository.cs: строка 19 в EID2.Tasks.UserTasks.CreateUser (CreateUserViewModel CreateUserViewModel) в C: \ Users \ csetzkorn \ Documents \ Visual Studio 2010 \ Projects \ EID2 \ Solutions \ EID2.Tasks \ UserTasks.cs: строка 33 в EID2.Web.Mvc.Controllers.UsersController.CreateUser (CreateUserViewModel CreateUserViewModel) в C: \ Users \ csetzkorn \ Documents \ Visual Studio 2010 \ Projects \ EID2 \ Solutions \ EID2.Web.Mvc \ Controllers \ UsersController.cs: строка 47

1 Ответ

1 голос
/ 24 июня 2011

Я думаю, что NHibernate извлекает экземпляр сущности из своего кэша первого уровня, что означает, что Save уже был вызван для сущности или настроен на сохранение из-за взаимосвязи.Является ли пользовательский объект таким же, как объект сущности?Если это так, вы можете проверить равенство ссылок:

if (user != entity) throw new ArgumentException("...");

Независимо от того, как заставить это работать, есть вероятность, что другая транзакция вставила пользователя с тем же адресом электронной почты между вашим чеком и совершенной транзакцией.,Для большинства приложений это небольшой риск, но я думаю, что лучший способ защититься от этого - это наложить уникальное ограничение на столбец базы данных и обработать исключение.

...