刘磊
2025-06-09 dabbcafc629ef87d11ba55ef8cc1cdc776c047d8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
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
    {
        /// <summary>
        /// 验证数据库字段类型与值是否正确,
        /// </summary>
        /// <param name="dbType">数据库字段类型(如varchar,nvarchar,decimal,不要带后面长度如:varchar(50))</param>
        /// <param name="value">值</param>
        /// <param name="propertyInfo">要验证的类的属性,若不为null,则会判断字符串的长度是否正确</param>
        /// <returns>(bool, string, object)bool成否校验成功,string校验失败信息,object,当前校验的值</returns>
        public static (bool, string, object) ValidationVal(this PropertyInfo propertyInfo, object value)
        {
            string dbType = "";
            SugarColumn sugarColumn = null;
            if (propertyInfo != null)
            {
                sugarColumn = propertyInfo.GetCustomAttribute<SugarColumn>();
                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<Type, string> ProperWithDbType = new Dictionary<Type, string>() {
            {  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<Dictionary<string, object>> dicList, bool removerKey, string[] ignoreFields = null)
        {
            PropertyInfo[] propertyInfo = typeinfo.GetProperties();
            string reslutMsg = string.Empty;
            foreach (Dictionary<string, object> dic in dicList)
            {
                reslutMsg = typeinfo.ValidateDicInEntity(dic, removerKey, propertyInfo, ignoreFields);
                if (!string.IsNullOrEmpty(reslutMsg))
                    return reslutMsg;
            }
            return reslutMsg;
        }
 
        /// <summary>
        /// 判断hash的列是否为对应的实体,并且值是否有效
        /// </summary>
        /// <param name="typeinfo"></param>
        /// <param name="dic"></param>
        /// <param name="removeNotContains">移除不存在字段</param>
        /// <param name="removerKey">移除主键</param>
        /// <returns></returns>
        public static string ValidateDicInEntity(this Type typeinfo, Dictionary<string, object> 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<SugarColumn>();
                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;
        }
 
        /// <summary>
        /// 安全获取字典值,如果键不存在或值为null则返回默认值
        /// </summary>
        /// <typeparam name="TKey">字典键的类型</typeparam>
        /// <typeparam name="TValue">字典值的类型</typeparam>
        /// <param name="dictionary">字典实例</param>
        /// <param name="key">键</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>字典值或默认值</returns>
        public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> 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<SugarColumn>();
                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<SugarColumn>();
                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<Navigate>();
                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<Navigate>();
                if (navigate is not null)
                {
                    return navigate.GetName();
                }
            }
            return null;
        }
 
        public static void SetDetailId<T>(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<Navigate>();
                if (navigate is not null)
                {
                    return property;
                }
            }
            return null;
        }
 
        public static object GetPropertyValue<T>(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;
        }
    }
}