我正在覆盖这样一个尖锐的架构存储库方法:
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始终返回一个实体,因此即使数据库中没有任何内容,也始终抛出异常。
有人能看出为什么会这样吗?应该不应该是这样的情况吗?我必须忽视一些明显的流血......
感谢。
基督教
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”}
at NHibernate.Impl.AbstractQueryImpl.UniqueElement(IList list) 在NHibernate.Impl.CriteriaImpl.UniqueResult() 在NHibernate.Impl.CriteriaImpl.UniqueResultT 位于C:\ Users \ csetzkorn \ Documents \ Visual Studio 2010 \ Projects \ EID2 \ Solutions \ EID2.Tasks \ Repositories \ UserRepository.cs中的EID2.Tasks.Repositories.UserRepository.SaveOrUpdate(用户实体):第19行 位于C:\ Users \ csetzkorn \ Documents \ Visual Studio 2010 \ Projects \ EID2 \ Solutions \ EID2.Tasks \ UserTasks.cs中的EID2.Tasks.UserTasks.CreateUser(CreateUserViewModel CreateUserViewModel):第33行 在C:\ Users \ csetzkorn \ Documents \ Visual Studio 2010 \ Projects \ EID2 \ Solutions \ EID2.Web.Mvc \ Controllers \ UsersController.cs中的EID2.Web.Mvc.Controllers.UsersController.CreateUser(CreateUserViewModel CreateUserViewModel):第47行
答案 0 :(得分:1)
我认为NHibernate正在从其第一级缓存中检索实体实例,这意味着已经在实体上调用了Save,或者由于关系而将其设置为持久化。用户对象与实体对象相同吗?如果是这样,您可以检查参考相等性:
if (user != entity) throw new ArgumentException("...");
无论您如何使用此功能,都有可能另一个事务在您的支票和提交的事务之间插入了具有相同电子邮件地址的用户。对于大多数应用程序来说这是一个小风险,但我认为防范这种情况的最佳方法是在数据库列上设置一个唯一约束并处理异常。