自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

白話Entity Framework Core數(shù)據(jù)驗(yàn)證

原創(chuàng)
開發(fā) 后端
數(shù)據(jù)驗(yàn)證是每個(gè)項(xiàng)目必須存在的,可以防止不符合系統(tǒng)規(guī)范的數(shù)據(jù)進(jìn)入系統(tǒng)進(jìn)而導(dǎo)致系統(tǒng)不穩(wěn)定甚至崩潰。我們可以自己編寫代碼進(jìn)行驗(yàn)證,但是這樣一方面代碼量較大,另一方面有可能驗(yàn)證代碼覆蓋不完全。但是在 Entity Framework Core (以下簡稱 EF Core )中這些問題全可以解決。

白話EF Core數(shù)據(jù)驗(yàn)證

【51CTO.com原創(chuàng)稿件】數(shù)據(jù)驗(yàn)證是每個(gè)項(xiàng)目必須存在的,可以防止不符合系統(tǒng)規(guī)范的數(shù)據(jù)進(jìn)入系統(tǒng)進(jìn)而導(dǎo)致系統(tǒng)不穩(wěn)定甚至崩潰。我們可以自己編寫代碼(包括前臺(tái)和后臺(tái)代碼)進(jìn)行驗(yàn)證,但是這樣一方面代碼量較大,另一方面有可能驗(yàn)證代碼覆蓋不完全。但是在 Entity Framework Core (以下簡稱 EF Core )中這些問題全可以解決。在 EF Core 中有兩種驗(yàn)證模式,分別是內(nèi)置模型驗(yàn)證和第三方擴(kuò)展模型驗(yàn)證。下面我分別對這兩種模式進(jìn)行講解,在講解前我們先來創(chuàng)建必須的模型。

  1. public class User 
  2.     public int Id { get; set; } 
  3.     public string Name { get; set; } 
  4.     public int Age { get; set; } 

一、內(nèi)置模型驗(yàn)證

在 EF Core 中并沒有 Fluent API 模式對數(shù)據(jù)進(jìn)行驗(yàn)證,因此我們只能通過 Data Annotations (數(shù)據(jù)注解)方式來進(jìn)行數(shù)據(jù)驗(yàn)證,也就是添加特性的方法來驗(yàn)證數(shù)據(jù)。例如我們要驗(yàn)證 User 模型中的 Name 的長度,Name 長度不能大于 5 ,我們只需在 Name 屬性上增加 StringLength 數(shù)據(jù)注解即可, StringLength 位于命名空間 System.ComponentModel.DataAnnotations 中,修改 User 模型代碼如下: 

  1. public class User 
  2.     public int Id { get; set; } 
  3.     [StringLength(5)] 
  4.     public string Name { get; set; } 
  5.     public int Age { get; set; } 

上述代碼通過 StringLength(5) 數(shù)據(jù)注解將 Name 屬性的數(shù)據(jù)長度限定在 5 ,并且在數(shù)據(jù)提交時(shí)按照這個(gè)約定進(jìn)行數(shù)據(jù)驗(yàn)證。下面我們就通過數(shù)據(jù)注解中的驗(yàn)證器來驗(yàn)證剛才添加的特性。首先我們要?jiǎng)?chuàng)建一個(gè)上下文的擴(kuò)展方法: 

  1. public static List<ValidationResult> ExecuteValidation(DbContext context) 
  2.     List<ValidationResult> result = new List<ValidationResult>(); 
  3.     var models = context.ChangeTracker.Entries() 
  4.         .Where(p => 
  5.         (p.State == EntityState.Added) || (p.State == EntityState.Modified)); 
  6.     foreach (var model in models) 
  7.     { 
  8.         var entity = model.Entity; 
  9.         var valProvider = new ValidationDbContextServiceProvider(context); 
  10.         var valContext = new ValidationContext(entity, valProvider, null); 
  11.         List<ValidationResult> error = new List<ValidationResult>(); 
  12.         if(!Validator.TryValidateObject(entity,valContext,error,true)) 
  13.         { 
  14.             result.AddRange(error); 
  15.         } 
  16.         return result.ToList(); 
  17.     } 

在上述代碼中我們通過 ChangeTracker 方法找出被追蹤的實(shí)體,然后過濾出需要添加和更新的實(shí)體,對這些實(shí)體進(jìn)行數(shù)據(jù)驗(yàn)證。最后我們通過 Validator 中的 TryValidateObject 方法驗(yàn)證實(shí)體數(shù)據(jù)并返回校驗(yàn)錯(cuò)誤信息。在業(yè)務(wù)代碼中我們調(diào)用前面定義的 ExecuteValidation 方法進(jìn)行驗(yàn)證,如果驗(yàn)證通過就調(diào)用 EF Core 的 SaveChange() 方法,如果未通過就調(diào)用相應(yīng)的處理代碼,代碼片段如下: 

  1. if(context.ExecuteValidation().Any()) 
  2.   foreach(var error in context.ExecuteValidation()) 
  3.   { 
  4.     //處理代碼 
  5.   } 
  6. else 
  7.   context.SaveChange(); 

講到這里估計(jì)會(huì)有很多小伙伴說每個(gè)業(yè)務(wù)代碼中都要這么寫太麻煩了,而且也產(chǎn)生了大量的重復(fù)代碼。那么重復(fù)代碼這個(gè)問題該怎么解決呢?這時(shí)一定有部分小伙伴想到了通過重寫 SaveChanges 方法,將驗(yàn)證代碼加入到這個(gè)方法中,這樣就可以解決剛才的那個(gè)問題,達(dá)到一勞永逸的效果。具體代碼如下: 

  1. public override int SaveChanges(bool acceptAllChangesOnSucces) 
  2.     var provider = ((IInfrastructure<IServiceProvider>)this).Instance; 
  3.     var items = new Dictionary<object, object>(); 
  4.     var models = this.ChangeTracker.Entries() 
  5.         .Where
  6.         p => (p.State == EntityState.Added)||(p.State==EntityState.Modified)); 
  7.     foreach (var model in models) 
  8.     { 
  9.         var entity = model.Entity; 
  10.         var context = new ValidationContext(entity, provider, items); 
  11.         List<ValidationResult> results = new List<ValidationResult>(); 
  12.         if(!Validator.TryValidateObject(entity,context,results,true)) 
  13.         { 
  14.             foreach (var result in results) 
  15.             { 
  16.                 if(result!=ValidationResult.Success) 
  17.                 { 
  18.                     throw new ValidationException(result.ErrorMessage); 
  19.                 } 
  20.             } 
  21.         } 
  22.     } 
  23.     return base.SaveChanges(); 

通過上述代碼就可以一處編寫驗(yàn)證,多處使用了。具體的思路和前面所講的一樣,這里就不再進(jìn)行講解了。

二、第三方擴(kuò)展模型驗(yàn)證

前面所講的是通過數(shù)據(jù)注解的方式來進(jìn)行數(shù)據(jù)驗(yàn)證的,但是如果是使用 Fluent API 的方式就沒辦法解決文章開頭所說的問題,因?yàn)镕luent API 模式并沒有提供對數(shù)據(jù)模型的驗(yàn)證。這時(shí)我們可以使用第三方擴(kuò)展,在 EF Core 中常用的模型數(shù)據(jù)驗(yàn)證第三方擴(kuò)展是 FluentValidation.AspNetCore 。在使用前我們需要在 NuGet 中下載此擴(kuò)展。 FluentValidation.AspNetCore 安裝完成后我們需要為模型創(chuàng)建驗(yàn)證器,驗(yàn)證器是一個(gè)繼承自 AbstractValidator<T> 的類,驗(yàn)證規(guī)則使用 RuleFor 方法定義在驗(yàn)證器構(gòu)造函數(shù)中。代碼如下: 

  1. public class ModelValidator:AbstractValidator<User
  2.     public ModelValidator() 
  3.     { 
  4.         RuleFor(p => p.Name).NotEmpty().WithMessage("姓名不能為空"); 
  5.         RuleFor(p => p.Name).MaximumLength(5).WithMessage("姓名長度在5字節(jié)"); 
  6.     } 

上述代碼進(jìn)行了兩個(gè)驗(yàn)證,一個(gè)是驗(yàn)證 Name 字段是否為空,另一個(gè)是驗(yàn)證 Name 字段的長度,其中我們通過 MaximumLength 規(guī)定了 Name 字段的最長長度為 5 字節(jié)。之后我們通過 WithMessage 方法返回我們自定義的錯(cuò)誤信息。 我們定義完驗(yàn)證規(guī)則后下一步就是將我們定義的驗(yàn)證規(guī)則與應(yīng)用程序連接起來,這里我們需要用到 AddFluentValidation 來注入,例如在 Asp.Net Core 程序中我們將注入程序?qū)懭?Startup 的 ConfigureServices 方法里。我們調(diào)用 AddFluentValidation 方法會(huì)將 FluentValidation 服務(wù)添加到 Asp.Net Core 中,然后使用 RegisterValidatorsFromAssembly 方法將自定義的驗(yàn)證代碼注入到容器中,代碼段如下: 

  1. public void ConfigureServices(IServiceCollection services) 
  2.   services.AddMvc() 
  3.     .AddFluentValidation(p=> 
  4.       p.RegisterValidatorsFromAssemblyContaining<Startup>()); 

在需要驗(yàn)證數(shù)據(jù)的地方我們通過 ModelState 獲取驗(yàn)證狀態(tài),驗(yàn)證通過就執(zhí)行后續(xù)代碼,不通過就執(zhí)行處理代碼。示例代碼如下: 

  1. if(ModelState.IsValid) 
  2.   //后續(xù)代碼 
  3. else 
  4.   //驗(yàn)證不通過處理代碼 

這里有一點(diǎn)需要注意,當(dāng)傳遞的實(shí)體為 null 時(shí),將返回錯(cuò)誤信息,這是因?yàn)?AbstractValidator 中存在 EnsureInstanceNotNull 方法,這個(gè)方法在實(shí)例為 null 時(shí)會(huì)拋出異常,即使重寫該方法也無法返回自定義的錯(cuò)誤信息。如果需要驗(yàn)證實(shí)體集合就需要使用 RuleForEach 方法即可,對于自定義驗(yàn)證規(guī)則則可使用 SetValidator 方法。

三、總結(jié)

本篇文章講解了 EF Core 數(shù)據(jù)驗(yàn)證的方法,雖然講的是 EF Core 的方法,但是同樣也適用于 EF6 ,這些內(nèi)容是常用的,上述部分代碼可以在大部分項(xiàng)目中通用。

作者簡介:

朱鋼,筆名喵叔,國內(nèi)某技術(shù)博客認(rèn)證專家,.NET高級開發(fā)工程師,7年一線開發(fā)經(jīng)驗(yàn),參與過電子政務(wù)系統(tǒng)和AI客服系統(tǒng)的開發(fā),以及互聯(lián)網(wǎng)招聘網(wǎng)站的架構(gòu)設(shè)計(jì),目前就職于一家初創(chuàng)公司,從事企業(yè)級安全監(jiān)控系統(tǒng)的開發(fā)。

【51CTO原創(chuàng)稿件,合作站點(diǎn)轉(zhuǎn)載請注明原文作者和出處為51CTO.com】

 

責(zé)任編輯:龐桂玉 來源: 51CTO
相關(guān)推薦

2024-06-18 12:58:12

2019-11-13 15:40:00

Entity Fram審計(jì)數(shù)據(jù)數(shù)據(jù)庫

2025-03-04 00:08:55

C#MySQL數(shù)據(jù)庫

2024-09-23 00:00:00

數(shù)據(jù)庫場景Entity

2012-07-20 10:38:25

Entity FramEF

2021-02-04 18:04:53

DbContext開源對象

2010-02-23 14:15:26

Entity Fram

2016-08-16 09:06:07

Entity FramT4模板sql語句

2009-12-22 14:46:09

ADO.NET Ent

2012-09-10 10:23:38

Entity Fram

2009-11-03 16:27:43

ADO.NET Ent

2009-12-30 14:03:36

ADO.NET Ent

2009-12-30 10:14:41

ADO.NET Ent

2011-03-30 14:08:01

Entity Fram跨數(shù)據(jù)庫查詢

2009-12-23 16:00:50

ADO.NET Ent

2009-12-22 17:14:37

ADO.NET Ent

2009-12-30 09:10:04

ADO.NET Ent

2011-03-30 13:14:05

Entity Fram

2009-12-23 16:15:24

ADO.NET Ent

2024-12-05 09:06:14

ORM框架.NET
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號