【发布时间】:2011-07-22 07:16:55
【问题描述】:
在使用基于 EF Code First 实现 ORM 时创建的 POCO 处理依赖于其他域实体的域实体验证时,有哪些最佳实践?
这是我正在尝试解决的情况:我有一个代表客户端计算机的类,并且该类的一个属性代表计算机的 IP。我需要它是独一无二的,但我找不到执行该约束的优雅解决方案。目前我在更新/插入实体的服务层中执行此操作。
-- 更新--
我知道 EF 不支持唯一约束,并且我已经将约束添加到数据库表中,但我宁愿在访问数据库之前捕获约束。我一直在寻找一种更好的方法来处理通常依赖于其他实体的验证,并以唯一约束为例。
-- 2010 年 3 月 28 日更新--
作为参考,这里是我目前处理 IP 唯一约束的方式(_unitOfWork 是 SqlMessageUnitOfWork 类型:基本上它围绕着我正在使用的 DBContext,为所有相关表公开 IDbSet):
public class ClientService : IClientService
{
public ValidationResult InsertClient(ClientDTO clientDTO)
{
var existingClient = _unitOfWork.Clients.Where(x => x.IP == clientDTO.IP).SingleOrDefault();
if (existingClient != null)
{
return new ValidationResult("IP already in Use.", new[] { "IP" });
}
else
{
var newclient = new Client();
ClientEntityMapper.MapToEntity(clientDTO, newclient, _unitOfWork.Terminals);
_unitOfWork.Clients.Add(newclient);
_unitOfWork.Commit();
}
return ValidationResult.Success;
}
...
private IUnitOfWork _unitOfWork;
public ClientService(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
}
public interface IUnitOfWork
{
IDbSet<Message> Messages { get; }
IDbSet<Terminal> Terminals { get; }
IDbSet<Client> Clients { get; }
IDbSet<MessageDisplayInstance> MessageDisplayInstances { get; }
void Commit();
}
public class SqlMessageUnitOfWork : IUnitOfWork
{
readonly VisualPagingDbContext _context;
public SqlMessageUnitOfWork()
{
_context = new VisualPagingDbContext();
}
public void Commit()
{
_context.SaveChanges();
}
public IDbSet<Message> Messages
{
get { return _context.Messages; }
}
public IDbSet<Terminal> Terminals
{
get { return _context.Terminals; }
}
public IDbSet<Client> Clients
{
get { return _context.Clients; }
}
public IDbSet<MessageDisplayInstance> MessageDisplayInstances
{
get { return _context.MessageDisplayInstances; }
}
}
【问题讨论】:
-
您没有展示您当前处理验证的方式,所以我们不知道您期望什么更好的方式。
-
我说我在服务层处理。我将通过输入实际代码来更新我的问题。
-
我不认为您可以在不查询数据库的情况下验证您的依赖属性。我在 BaseRepository 类中将 IsValid() 方法定义为虚拟方法,并在其他存储库中覆盖它,从而在服务层中的单个方法中进行所有验证。
-
我同意,虽然我忘记了这个问题的细节,但我真的不再使用这样的服务类了。对我来说,他们隐藏了所有肮脏的小秘密,当他们吐出基于存储库/域/服务洋葱的架构时,没有人谈论这些秘密。您无法回避这样一个事实,即验证(或一般的业务逻辑)有时取决于其他实体的状态,这往往会被推入“服务层”。对我来说,它直接属于业务模型,所以我认为它违反了层级责任。
标签: .net entity-framework ef-code-first