[英].EFCore - Is it possible to create data annotation validation based on the column max size in the database?
我不想查看數據庫列定義,而是希望根據數據庫中的列大小進行最大maxlength
驗證,這可能嗎?
我問是因為我的一些列是varchar
,有些是nvarchar
,有時會導致混淆,因為對於varchar
,如果max
為 100,那么您可以插入 100 個字符,但如果它是最大為 100 的 nvarchar,則可以僅插入 50 個字符.
我想停止這種混亂,這可能嗎?
您可以使用 EF 運行自定義 SQL 查詢以讀取有關表的元信息。 SQL 查詢取決於您使用的實際數據庫。 對於 MySQL,我使用EXPLAIN table
來獲取有關表的元信息。 此信息將通過您正在使用的 EF 上下文在名為ExplainInfo
的實體中讀取。
對於驗證,您可以創建一個從ValidationAttribute
擴展的新驗證類/屬性並覆蓋IsValid(object value, ValidationContext validationContext)
方法。 ValidationContext
參數很重要,因為我們必須將當前打開的上下文注入驗證器,並獲取有關要驗證的實體類型和屬性名稱的信息。 我們使用它來發送一個查詢,該查詢獲取有關列的信息並針對它驗證當前值。
作為概念驗證,解決方案可能如下所示:
(作為余數, EXPLAIN table
的結果如下所示:)
mysql> EXPLAIN Author;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| Id | int | NO | PRI | NULL | auto_increment |
| Name | varchar(30) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
首先,我們為EXPLAIN
查詢的結果創建一個實體:
public class ExplainInfo
{
[Key]
public string Field {get; set;}
public string Type {get; set;}
}
要使用它,我們必須像往常一樣在上下文中添加一個新的DbSet
條目:
public DbSet<ExplainInfo> ExplainInfo {get; set;}
然后我們編寫新的驗證屬性:
public class LimitValidationAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
MyContext context = (MyContext)validationContext.Items["context"];
string entityName = validationContext.ObjectType.Name;
string propertyName = validationContext.MemberName;
IList<ExplainInfo> metaInfo = context.ExplainInfo.FromSqlRaw($"EXPLAIN {entityName}").ToList();
ExplainInfo singleExplainInfo = metaInfo.Single(it => it.Field == propertyName);
string databaseType = singleExplainInfo.Type.ToLowerInvariant();
if (databaseType.StartsWith("varchar("))
{
string regexStr = @"varchar\((\d+)\)";
Regex regex = new Regex(regexStr);
Match match = regex.Match(databaseType);
string limitAsString = match.Groups[1].Value;
int limit = int.Parse(limitAsString);
string valueAsString = (string)value;
if (valueAsString.Length > limit) {
return new ValidationResult("The given value for the property "+propertyName+" exceed the limit of "+limit+" characters defined in the database");
}
}
return ValidationResult.Success;
}
}
我們將在實體中使用此驗證屬性:
public class Author
{
// [...]
[LimitValidation]
public string Name {get; set;}
// [...]
}
最后我們將觸發驗證:
using (MyContext context = new MyContext())
{
Author author = context.Author.First();
ValidationContext validationContext = new ValidationContext(author, new Dictionary<object, object> {
{"context", context}
});
author.Name += "dummy text which will exceed the limit in the database";
Validator.ValidateObject(author, validationContext, true);
context.SaveChanges();
}
這將生成以下驗證異常:
屬性名稱的給定值超出了數據庫中定義的 30 個字符的限制
您必須調整VARCHAR
和NVARCHAR
類型的IsValid()
方法以及獲取表元信息的查詢。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.