using SqlSugar;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using WIDESEA_Core.Const;
using WIDESEA_Core.DB.Models;
using WIDESEA_Core.Helper;
namespace WIDESEA_Core.Utilities
{
public static class EntityProperties
{
///
/// 验证数据库字段类型与值是否正确,
///
/// 数据库字段类型(如varchar,nvarchar,decimal,不要带后面长度如:varchar(50))
/// 值
/// 要验证的类的属性,若不为null,则会判断字符串的长度是否正确
/// (bool, string, object)bool成否校验成功,string校验失败信息,object,当前校验的值
public static (bool, string, object) ValidationVal(this PropertyInfo propertyInfo, object value)
{
string dbType = "";
SugarColumn sugarColumn = null;
if (propertyInfo != null)
{
sugarColumn = propertyInfo.GetCustomAttribute();
dbType = propertyInfo != null ? propertyInfo.GetProperWithDbType() : SqlDbTypeName.NVarChar;
}
dbType = dbType.ToLower();
string val = value?.ToString();
//验证长度
string reslutMsg = string.Empty;
if (dbType == SqlDbTypeName.Int)
{
if (!value.IsInt())
reslutMsg = "只能为有效整数";
} //2021.10.12增加属性校验long类型的支持
else if (dbType == SqlDbTypeName.BigInt)
{
if (!long.TryParse(val, out _))
{
reslutMsg = "只能为有效整数";
}
}
else if (dbType == SqlDbTypeName.DateTime
|| dbType == SqlDbTypeName.Date
|| dbType == SqlDbTypeName.SmallDateTime
|| dbType == SqlDbTypeName.SmallDate
)
{
if (!value.IsDate())
reslutMsg = "必须为日期格式";
}
else if (dbType == SqlDbTypeName.Float || dbType == SqlDbTypeName.Decimal || dbType == SqlDbTypeName.Double)
{
if (!val.IsNumber(null))
{
reslutMsg = "不是有效数字";
}
}
else if (dbType == SqlDbTypeName.UniqueIdentifier)
{
if (!val.IsGuid())
{
reslutMsg = propertyInfo.Name + "Guid不正确";
}
}
else if (propertyInfo != null
&& (dbType == SqlDbTypeName.VarChar
|| dbType == SqlDbTypeName.NVarChar
|| dbType == SqlDbTypeName.NChar
|| dbType == SqlDbTypeName.Char
|| dbType == SqlDbTypeName.Text))
{
//默认nvarchar(max) 、text 长度不能超过20000
if (val.Length > 200000)
{
reslutMsg = $"字符长度最多【200000】";
}
else
{
int length = sugarColumn.Length;
if (length == 0) { return (true, null, null); }
//判断双字节与单字段
else if (length < 8000 &&
((dbType.Substring(0, 1) != "n"
&& Encoding.UTF8.GetBytes(val.ToCharArray()).Length > length)
|| val.Length > length)
)
{
reslutMsg = $"最多只能【{length}】个字符。";
}
}
}
if (!string.IsNullOrEmpty(reslutMsg) && propertyInfo != null)
{
reslutMsg = sugarColumn.ColumnDescription + reslutMsg;
}
return (reslutMsg == "" ? true : false, reslutMsg, value);
}
private static readonly Dictionary ProperWithDbType = new Dictionary() {
{ typeof(string),SqlDbTypeName.NVarChar },
{ typeof(DateTime),SqlDbTypeName.DateTime},
{typeof(long),SqlDbTypeName.BigInt },
{typeof(int),SqlDbTypeName.Int},
{ typeof(decimal),SqlDbTypeName.Decimal },
{ typeof(float),SqlDbTypeName.Float },
{ typeof(double),SqlDbTypeName.Double },
{ typeof(byte),SqlDbTypeName.Int },//类型待完
{ typeof(Guid),SqlDbTypeName.UniqueIdentifier}
};
public static string GetProperWithDbType(this PropertyInfo propertyInfo)
{
bool result = ProperWithDbType.TryGetValue(propertyInfo.PropertyType, out string value);
if (result)
{
return value;
}
return SqlDbTypeName.NVarChar;
}
public static string ValidateDicInEntity(this Type typeinfo, List> dicList, bool removerKey, string[] ignoreFields = null)
{
PropertyInfo[] propertyInfo = typeinfo.GetProperties();
string reslutMsg = string.Empty;
foreach (Dictionary dic in dicList)
{
reslutMsg = typeinfo.ValidateDicInEntity(dic, removerKey, propertyInfo, ignoreFields);
if (!string.IsNullOrEmpty(reslutMsg))
return reslutMsg;
}
return reslutMsg;
}
///
/// 判断hash的列是否为对应的实体,并且值是否有效
///
///
///
/// 移除不存在字段
/// 移除主键
///
public static string ValidateDicInEntity(this Type typeinfo, Dictionary dic, bool removerKey, PropertyInfo[] propertyInfo, string[] ignoreFields = null)
{
if (dic == null || dic.Count == 0) { return "参数无效"; }
// 不存在的字段直接移除
dic.Where(x => !propertyInfo.Any(p => p.Name == x.Key.FirstLetterToUpper())).Select(s => s.Key).ToList().ForEach(f =>
{
dic.Remove(f);
});
string keyName = typeinfo.GetKeyName();
//移除主键
if (removerKey)
dic.Remove(keyName);
//else
//{
// if (!dic.ContainsKey(keyName))
// return "请传入主键参数";
//}
foreach (PropertyInfo property in propertyInfo)
{
SugarColumn sugarColumn = property.GetCustomAttribute();
if (sugarColumn == null)
return "请配置SugarColumn属性";
//忽略与主键的字段不做验证
if (property.Name == keyName.FirstLetterToUpper() || (ignoreFields != null && ignoreFields.Contains(property.Name)) || sugarColumn.IsOnlyIgnoreInsert || sugarColumn.IsOnlyIgnoreUpdate || sugarColumn.IsIgnore)
continue;
//不在编辑中的列,是否也要必填
if (!dic.ContainsKey(property.Name.FirstLetterToLower()))
{
if (!sugarColumn.IsNullable)
{
if (sugarColumn.DefaultValue != null)
return sugarColumn.ColumnDescription + "为必须提交项";
continue;
}
continue;
}
string str = dic.GetValueOrDefault(property.Name.FirstLetterToLower(), "").ToString();
//将所有空值设置为null
if (dic[property.Name.FirstLetterToLower()] != null && str == string.Empty)
dic[property.Name.FirstLetterToLower()] = null;
}
return string.Empty;
}
///
/// 安全获取字典值,如果键不存在或值为null则返回默认值
///
/// 字典键的类型
/// 字典值的类型
/// 字典实例
/// 键
/// 默认值
/// 字典值或默认值
public static TValue GetValueOrDefault(this IDictionary dictionary, TKey key, TValue defaultValue = default)
{
if (dictionary == null) throw new ArgumentNullException(nameof(dictionary));
return dictionary.TryGetValue(key, out TValue value) && value != null ? value : defaultValue;
}
public static string GetKeyName(this Type typeinfo)
{
return typeinfo.GetProperties().GetKeyName();
}
public static string GetKeyName(this PropertyInfo[] properties)
{
foreach (PropertyInfo property in properties)
{
SugarColumn sugarColumn = property.GetCustomAttribute();
if (sugarColumn.IsPrimaryKey)
return property.Name;
}
return null;
}
public static PropertyInfo GetKeyProperty(this Type typeinfo)
{
PropertyInfo[] properties = typeinfo.GetProperties();
foreach (PropertyInfo property in properties)
{
SugarColumn sugarColumn = property.GetCustomAttribute();
if (sugarColumn?.IsPrimaryKey ?? false)
{
return property;
}
}
return null;
}
public static Type GetDetailType(this Type typeinfo)
{
PropertyInfo[] properties = typeinfo.GetProperties();
foreach (PropertyInfo property in properties)
{
Navigate? navigate = property.GetCustomAttribute();
if (navigate is not null)
{
if (navigate.GetNavigateType() == NavigateType.OneToOne)
return property.PropertyType;
else
return property.PropertyType.GenericTypeArguments[0];
}
}
return null;
}
public static string GetMainIdByDetail(this Type typeinfo)
{
PropertyInfo[] properties = typeinfo.GetProperties();
foreach (PropertyInfo property in properties)
{
Navigate? navigate = property.GetCustomAttribute();
if (navigate is not null)
{
return navigate.GetName();
}
}
return null;
}
public static void SetDetailId(this Type typeinfo, T enetiy, object id, string name)
{
PropertyInfo property = typeinfo.GetProperty(name);
if (property != null)
{
property.SetValue(enetiy, id);
}
}
public static PropertyInfo? GetNavigatePro(this Type typeinfo)
{
PropertyInfo[] properties = typeinfo.GetProperties();
foreach (PropertyInfo property in properties)
{
Navigate? navigate = property.GetCustomAttribute();
if (navigate is not null)
{
return property;
}
}
return null;
}
public static object GetPropertyValue(this Type typeinfo, T data, string propertyName)
{
if (typeinfo != typeof(T))
return null;
PropertyInfo? property = typeinfo.GetProperty(propertyName);
if (property != null)
{
return property.GetValue(data);
}
return null;
}
}
}