.net EF代码第一个CTP 5:验证依赖于其他实体的实体(例如唯一约束)
对于依赖于使用POCO的其他域实体的域实体的验证,有哪些最佳实践是在首先实现基于EF代码的ORM时创建的 下面是我正在尝试解决的情况:我有一个表示客户端计算机的类,该类的一个属性表示计算机的IP。我需要它是唯一的,但我找不到一个优雅的解决方案来强制执行该约束。目前,我在服务层中更新/插入实体 --更新-- 我知道EF不支持唯一约束,并且我已经将约束添加到数据库表中,但是我宁愿在访问数据库之前捕获约束。我一直在寻找一种更好的方法来处理通常依赖于其他实体的验证,并以unique约束为例 --更新日期:3/28/2010-- 以下是我当前处理IP唯一约束的方式(unitOfWork的类型为SqlMessageUnitOfWork:基本上它围绕我正在使用的DBContext进行包装,为所有相关表公开IDbSets),以供参考:.net EF代码第一个CTP 5:验证依赖于其他实体的实体(例如唯一约束),.net,entity-framework,ef-code-first,.net,Entity Framework,Ef Code First,对于依赖于使用POCO的其他域实体的域实体的验证,有哪些最佳实践是在首先实现基于EF代码的ORM时创建的 下面是我正在尝试解决的情况:我有一个表示客户端计算机的类,该类的一个属性表示计算机的IP。我需要它是唯一的,但我找不到一个优雅的解决方案来强制执行该约束。目前,我在服务层中更新/插入实体 --更新-- 我知道EF不支持唯一约束,并且我已经将约束添加到数据库表中,但是我宁愿在访问数据库之前捕获约束。我一直在寻找一种更好的方法来处理通常依赖于其他实体的验证,并以unique约束为例 --更新日期
公共类ClientService:IClientService
{
公共验证结果插入客户端(客户端到客户端)
{
var existingClient=_unitOfWork.Clients.Where(x=>x.IP==clientDTO.IP).SingleOrDefault();
if(existingClient!=null)
{
返回新的ValidationResult(“IP已在使用中。”,新[]{“IP”});
}
其他的
{
var newclient=newclient();
ClientEntityMapper.MapToEntity(clientDTO、newclient、_unitOfWork.Terminals);
_unitOfWork.Clients.Add(newclient);
_unitOfWork.Commit();
}
返回ValidationResult.Success;
}
...
私人工作单位;
公共客户端服务(IUnitOfWork unitOfWork)
{
_unitOfWork=unitOfWork;
}
}
公共接口工作单元
{
IDbSet消息{get;}
IDbSet终端{get;}
IDbSet客户端{get;}
IDbSet MessageDisplayInstances{get;}
无效提交();
}
公共类SqlMessageUnitOfWork:IUnitOfWork
{
只读VisualPagingDbContext\u context;
公共SqlMessageUnitOfWork()
{
_context=新的VisualPagingDbContext();
}
公共无效提交()
{
_SaveChanges();
}
公共IDbSet消息
{
获取{return\u context.Messages;}
}
公共设备终端
{
获取{return\u context.Terminals;}
}
公共IDbSet客户端
{
获取{return\u context.Clients;}
}
公共IDbSet MessageDisplayInstances
{
获取{return\u context.MessageDisplayInstances;}
}
}
唯一约束完全不受EF支持(),但这并不意味着您不能将它们添加到数据库表中(例如在自定义初始值设定项中)。您描述的是需要查询数据库的验证。它是一种业务验证,必须在需要时实施和执行。这不是EF将为您处理的事情。顺便说一句,CTP5是过时的版本。使用。如果需要设置唯一约束,可以通过运行sql命令来完成
因此,无论您在哪里进行域模型配置,都可以添加一行来执行sql。因此,在您的情况下,应采用以下方法:
string script = "ALTER TABLE <table-name> ADD CONSTRAINT UniqueElement UNIQUE (<column-name>)";
context.Database.SqlCommand(script);
string script=“ALTER TABLE ADD CONSTRAINT uniquelement UNIQUE()”;
context.Database.SqlCommand(脚本);
要在实体验证中添加唯一性检查,我在上下文中重写了ValidateEntity,并添加了以下内容:
if (entityEntry.Entity is Role &&
(entityEntry.State == EntityState.Added || entityEntry.State == EntityState.Modified))
{
var role = entityEntry.Entity as Role;
if (!string.IsNullOrEmpty(role.ShortName))
{
if (
Roles.Any(
p => p.ShortName.ToLower() == role.ShortName.ToLower() && !p.RoleID.Equals(role.RoleID)))
{
result.ValidationErrors.Add(new DbValidationError("ShortName", "Role Short Name already exists"));
return result.ValidationErrors.Count > 0 ? result : base.ValidateEntity(entityEntry, items);
}
//Remeber to check local collection - otherwise we could end up saving two or more at once that are duplicated
if (
Roles.Local.Count(p => p.ShortName.ToLower() == role.ShortName.ToLower() && !p.Equals(role)) > 0)
{
result.ValidationErrors.Add(new DbValidationError("ShortName", "Role Short Name already exists"));
return result.ValidationErrors.Count > 0 ? result : base.ValidateEntity(entityEntry, items);
}
}
}
如果需要获取EF以在数据库中创建约束/索引等,请参见:
感谢您让我知道4.1已经过时。您没有展示您当前处理验证的方式,因此我们不知道您希望有什么更好的方式。我说我是在服务层处理的。我将通过输入实际代码来更新我的问题。我认为如果不查询数据库,就无法验证依赖属性。我在我的BaseRepository类中将IsValid()方法定义为虚拟方法,并在其他存储库中重写它,在服务层的单个方法中进行所有验证。我同意,尽管我忘记了这个问题的细节,但我不再真正使用这样的服务类。对我来说,他们隐藏了所有肮脏的小秘密,当他们在那里谈论基于存储库/域/服务的体系结构时,没有人谈论这些秘密。您无法回避验证(或一般业务逻辑)有时依赖于其他实体的状态这一事实,这往往会被推到“服务层”。对我来说,它直接属于业务模型,因此我认为它违反了层责任。我的问题不是如何创建唯一的约束,而是如何在我的应用程序代码中更好地对它们建模。
if (entityEntry.Entity is Role &&
(entityEntry.State == EntityState.Added || entityEntry.State == EntityState.Modified))
{
var role = entityEntry.Entity as Role;
if (!string.IsNullOrEmpty(role.ShortName))
{
if (
Roles.Any(
p => p.ShortName.ToLower() == role.ShortName.ToLower() && !p.RoleID.Equals(role.RoleID)))
{
result.ValidationErrors.Add(new DbValidationError("ShortName", "Role Short Name already exists"));
return result.ValidationErrors.Count > 0 ? result : base.ValidateEntity(entityEntry, items);
}
//Remeber to check local collection - otherwise we could end up saving two or more at once that are duplicated
if (
Roles.Local.Count(p => p.ShortName.ToLower() == role.ShortName.ToLower() && !p.Equals(role)) > 0)
{
result.ValidationErrors.Add(new DbValidationError("ShortName", "Role Short Name already exists"));
return result.ValidationErrors.Count > 0 ? result : base.ValidateEntity(entityEntry, items);
}
}
}