自定义ValidateEntity实体验证及DB层面Interception拦截EF中的Execute

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自定义ValidateEntity实体验证及DB层面Interception拦截EF中的Execute相关的知识,希望对你有一定的参考价值。

一:ef的注入或者拦截或者扩展

1. DBContext。。。 是否有被注入的点。。。


Controller下面有很多的override行为。。。

《1》 ShouldValidateEntity 是否需要验证实体

触发点: SaveChanges的时候 (CURD)一些操作。


针对这些操作,我们可能会有一些entity的针对性的验证操作。。。

jquery.validator...
mvc中的 binding的操作。【DataAnotation】

 


《2》 ValidateEntity 具体的验证行为

 

《3》SaveChange的源代码中进行ShouldValidateEntity角度分析


用ILSpy搞定。。。

// System.Data.Entity.Internal.InternalContext
public virtual int SaveChanges()
{
int result;
try
{
if (this.ValidateOnSaveEnabled)
{
IEnumerable<DbEntityValidationResult> validationErrors = this.Owner.GetValidationErrors();
if (validationErrors.Any<DbEntityValidationResult>())
{
throw new DbEntityValidationException(Strings.DbEntityValidationException_ValidationFailed, validationErrors);
}
}
bool flag = this.AutoDetectChangesEnabled && !this.ValidateOnSaveEnabled;
SaveOptions options = SaveOptions.AcceptAllChangesAfterSave | (flag ? SaveOptions.DetectChangesBeforeSave : SaveOptions.None);
result = this.ObjectContext.SaveChanges(options);
}
catch (UpdateException updateException)
{
throw this.WrapUpdateException(updateException);
}
return result;
}


public IEnumerable<DbEntityValidationResult> GetValidationErrors()
{
List<DbEntityValidationResult> list = new List<DbEntityValidationResult>();
foreach (DbEntityEntry current in this.ChangeTracker.Entries())
{
if (current.InternalEntry.EntityType != typeof(EdmMetadata) && this.ShouldValidateEntity(current))
{
DbEntityValidationResult dbEntityValidationResult = this.ValidateEntity(current, new Dictionary<object, object>());
if (dbEntityValidationResult != null && !dbEntityValidationResult.IsValid)
{
list.Add(dbEntityValidationResult);
}
}
}
return list;
}

 

三:对StudentName进行验证

protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
{
//开始做自定义验证: 比如我们的StudentName的值必须不能是“test”。如果是test将会抛出异常

return base.ValidateEntity(entityEntry, items);
}


if (this.ValidateOnSaveEnabled)
{
IEnumerable<DbEntityValidationResult> validationErrors = this.Owner.GetValidationErrors();
if (validationErrors.Any<DbEntityValidationResult>())
{
throw new DbEntityValidationException(Strings.DbEntityValidationException_ValidationFailed, validationErrors);
}
}


四: 在CURD的Database层面进行拦截,进行监控,这样的话方便我们记录log。。。

 

核心接口: IDbCommandInterceptor

1. 自定义类实现接口

2. 注入到entity framework中。。。通过appconfig的形式。。。


UPDATE [dbo].[Student]
SET [StudentName] = @0
WHERE ([StudentID] = @1)
SELECT [RowVersion]
FROM [dbo].[Student]
WHERE @@ROWCOUNT > 0 AND [StudentID] = @1

记录日志。。。

DataBase.Log 方法。。。。

以上是关于自定义ValidateEntity实体验证及DB层面Interception拦截EF中的Execute的主要内容,如果未能解决你的问题,请参考以下文章

Blazor入门100天 : 身份验证和授权

.NET MVC 数据处理

如何使用 Spring + Hibernate 对实体进行自定义验证以进行多租户设置

CakePHP 3自定义验证:如何在编辑期间将新值与旧值进行比较?

Symfony2 实体用户提供者覆盖自定义身份验证提供者

实体框架:创建自定义属性