.NET 数据合理性校验浅谈

仅仅个人的一点小总结,把数据校验分为横向校验与纵向校验;

横向:对各个属性的单独或多个一起比较,如用户注册的信息,邮箱是否符合格式等,2次输入的密码是否一致,密码的复杂度等,这类验证方法很多,可以自己给属性加特性标志,然后统一方法验证,自己定规则啦,还有很多其他框架可以使用;

纵向:如用户注册的邮箱地址、手机号码,现有用户是否已经使用了,简单说就是和同类比,当然还有其他的;

来个例子:

还是2个实体

 1     public class Room
 2     {
 3         public int Id { get; set; }
 4         public string Number { get; set; }
 5         public string Building { get; set; }
 6         public string Address
 7         {
 8             get
 9             {
10                 if (Number != null && Building != null)
11                 {
12                     return Building + Number;
13                 }
14                 return "";
15             }
16         }
17         public int Max { get; set; }
18     }
 1  public class Student
 2     {
 3         public int Id { get; set; }
 4         public string Name
 5         {
 6             get;
 7             set;
 8         }
 9         public DateTime Brithday
10         {
11             get;
12             set;
13         }
14 
15         public double High
16         {
17             get;
18             set;
19         }
20 
21         public decimal Money
22         {
23             get;
24             set;
25         }
26 
27         public bool Enable
28         {
29             get;
30             set;
31         }
32 
33         public int? RoomId
34         {
35             get;
36             set;
37         }
38         public Room Room
39         {
40             get;
41             set;
42         }
43         public double Qty
44         {
45             get;
46             set;
47         }
48         public string TelNumber { get; set; }
49         public decimal Price
50         {
51             get;
52             set;
53         }
54 
55     }

简单模拟一些数据:

 1     /// <summary>
 2     /// 模拟数据源
 3     /// </summary>
 4     public static class Database
 5     {
 6         public static List<Room> Rooms { get; set; }
 7 
 8 
 9         public static List<Student> Students { get; set; }
10         static Database()
11         {
12             #region 添加模拟数据
13             if (Rooms == null)
14             {
15                 Rooms = new List<Room>{new Room { Id=1, Number="101", Building="A栋", Max=8 }};
16             }
17             #endregion
18             if(Students==null)
19             {
20                 Students = new List<Student>();
21                 Room r1 = Rooms.FirstOrDefault();
22                 for (int i = 0; i < 5; i++)
23                 {
24                     Student stu = new Student { Id = i + 1, RoomId = r1.Id, Room = r1, Brithday = DateTime.Now.AddYears(-20), High = 170.5 + i, Money = 200000.5m + i, Name = "Jack" + i };
25                     if (i == 2)
26                         stu.TelNumber = "18866668888";
27                     Students.Add(stu);
28                 }
29             }
30         }
31     }

使用FluentValidation,添加AbstractValidator子类,在构造方法中添加对Student实体校验的规则,属于横向校验

 1  public class StudentValidator: AbstractValidator<Student>
 2     {
 3         public StudentValidator()
 4         {
 5             RuleFor(stu => stu.Brithday).LessThanOrEqualTo(DateTime.Now.AddYears(-18)).WithMessage("年龄不能小于18周岁");
 6             RuleFor(stu => stu.High).LessThanOrEqualTo(250).WithMessage("身高不能大于250cm");
 7             RuleFor(stu => stu.Money).InclusiveBetween(100000, 100000000).WithMessage("10万到1亿之间的资产才能读书");
 8             RuleFor(stu => stu.Price).GreaterThan(0).WithMessage("价格必须大于0");
 9         }
10     }

控制台验证看看:

 1   class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             #region 横向校验,可以放到客户端校验,基本上服务器在api接收到数据也要校验
 6             ////提交上来的数据,身高3000cm,2年前出生
 7             //Student stu = new Student { High = 3000, Brithday = DateTime.Now.AddYears(-2),Money=100000,Price=-1 };
 8             //StudentValidator validator = new StudentValidator();
 9             //var result=validator.Validate(stu);
10             //if (!result.IsValid)
11             //{
12             //    var msgList= result.Errors.Select(a => a.ErrorMessage);
13             //    Console.WriteLine("实体验证失败:\r\n"+string.Join(";",msgList));
14             //    return;
15             //}
16             #endregion
17 
18             #region 纵向校验,假设已经通过横向校验;一般放到业务层
19             //业务场景:添加Student给他分配Room,检查该Room是否还有位置
20             Room r1 = Database.Rooms.FirstOrDefault();
21 
22             Student stu = new Student { TelNumber = "18866668888", Name = "Bob", High = 180, Brithday = DateTime.Now.AddYears(-20), RoomId = r1.Id, Room = r1 };
23             bool pass = false;
24             string validResult = Valid(stu, out pass);
25             Console.WriteLine(validResult);
26             if (pass)
27             {
28                 //通过校验,继续
29                 Console.WriteLine("写入数据库...");
30                 Database.Students.Add(stu);
31         
32                 Console.WriteLine($"我住到{r1.Number}啦,我们一共{Database.Students.Where(a => a.RoomId == r1.Id).Count()}人");
33             }
34 
35             #endregion
36         }
37         public static string Valid(Student stu, out bool pass)
38         {
39      
40             if (Database.Students.Exists(a => a.TelNumber == stu.TelNumber))
41             {
42                 pass = false;
43                 return "你这个电话号码有人用了";
44             }
45             Room r1 = Database.Rooms.FirstOrDefault(a => a.Id == stu.RoomId);
46             if (r1 == null)
47             {
48                 pass = false;
49                 return "不存在该宿舍啊";
50             }
51 
52 
53             int max = r1.Max;
54             int currentNum = Database.Students.Where(a => a.RoomId == r1.Id).Count();
55             if (max > currentNum)
56             {
57                 pass = true;
58                 return $"最多住{max}人,现在住{currentNum}人,还有位置";
59             }
60             else
61             {
62                 pass = false;
63                 return "人满了";
64             }
65 
66         }
67     }

Over

另外,在.NET MVC开发方式,给实体添加验证的特性,生成的视图模板同样可以在浏览器端进行验证,主要通过jquery.validate.js与jquery.validate.unobtrusive.js进行校验,都属于横向的校验。

posted @ 2020-10-30 16:26  独立思考者  阅读(395)  评论(0)    收藏  举报