EF Code First CTP 5:验证依赖于其他实体的实体(例如唯一约束)
对于依赖于使用 POCO(在实现基于 EF Code First 的 ORM 时创建的 POCO)的其他域实体来处理域实体的验证,有哪些最佳实践?
这是我试图解决的情况:我有一个代表客户端计算机的类,并且该类的一个属性代表计算机的 IP。我需要它是唯一的,但我找不到一个优雅的解决方案来强制执行该约束。目前,我在更新/插入实体的服务层中执行此操作。
-- 更新 --
我知道 EF 不支持唯一约束,并且我已经将约束添加到数据库表中,但我宁愿在访问数据库之前捕获约束。我正在寻找一种更好的方法来处理通常依赖于其他实体的验证,并使用唯一约束作为示例。
-- 更新 3/28/2010 --
作为参考,以下是我当前处理 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; }
}
}
What are some best practices for handling validation of domain entities that depends on other domain entities using POCOs that one creates when implementing an ORM based off of the EF Code First?
Here's the situation I am trying to work through: I have a class that represents a client computer, and there is a property of that class that represents the computer's IP. I need that to be unique, but I cannot find an elegant solution for enforcing that constraint. Currently I do it in the service layer where I update/insert the entity.
-- UPDATE --
I know that EF doesn't support unique constraints and I have already added the constraint to the database table, but I'd rather catch the constraint before I hit the database. What I was looking for was a better way to handle validation that is dependent on other entities in general and was using the unique constraint as an example.
-- UPDATE 3/28/2010 --
For reference, here is how I currently handle the unique constraint for IP (_unitOfWork is of type SqlMessageUnitOfWork: basically it wraps around the DBContext I am using, exposing IDbSets for all relevant tables):
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; }
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
EF 根本不支持唯一约束(它们是计划用于未来版本),但这并不意味着您不能将它们添加到数据库表中(例如在自定义初始值设定项中)。您所描述的是需要查询数据库的验证。这是一种必须在需要时实施和执行的业务验证。这不是 EF 会为您处理的事情。顺便提一句。 CTP5 是过时的版本。请改用 EF 4.1 。
Unique constraints are not supported by EF at all (they are planned for future versions) but it doesn't mean you can't add them to your database tables (for example in custom initializer). What you describe is validation which requires query to database. It is a business validation which must be implemented and executed when needed. It is not something that EF will handle for you. Btw. CTP5 is outdated version. Use EF 4.1 instead.
如果您需要设置唯一约束,可以通过运行 sql 命令来完成。
因此,无论您在哪里进行域模型配置,都可以添加一行来执行 sql。因此,在您的情况下,以下内容应该可以完成这项工作:
If you need to setup unique constraints you can do it through running a sql command.
So wherever you do your domain model configurations, you can add a line to execute a sql. So in your case the following should do the job:
为了向我的实体验证添加唯一性检查,我在上下文中覆盖了 ValidateEntity 并添加了以下内容:
如果您需要使用 EF 在数据库中创建约束/索引等,请参阅:
实体框架代码优先 Fluent Api:向列添加索引
To add uniqueness checking to my entity validation, I overrode ValidateEntity in the context and added the following:
If you need to get EF to create constraints / indexes etc in the database, then please see:
Entity Framework Code First Fluent Api: Adding Indexes to columns