iotgateway/WalkingTec.Mvvm/WalkingTec.Mvvm.Core/BaseCRUDVM.cs

1055 lines
45 KiB
C#
Raw Normal View History

2021-12-14 06:10:44 +00:00
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using WalkingTec.Mvvm.Core.Extensions;
using WalkingTec.Mvvm.Core.Support.FileHandlers;
namespace WalkingTec.Mvvm.Core
{
/// <summary>
/// 单表增删改查VM的接口
/// </summary>
/// <typeparam name="T">继承TopBasePoco的类</typeparam>
public interface IBaseCRUDVM<out T> where T : TopBasePoco, new()
{
T Entity { get; }
/// <summary>
/// 根据主键Id获取Entity
/// </summary>
/// <param name="id">主键Id</param>
void SetEntityById(object id);
/// <summary>
/// 设置Entity
/// </summary>
/// <param name="entity">要设定的TopBasePoco</param>
void SetEntity(object entity);
/// <summary>
/// 添加
/// </summary>
void DoAdd();
Task DoAddAsync();
/// <summary>
/// 修改
/// </summary>
void DoEdit(bool updateAllFields);
Task DoEditAsync(bool updateAllFields);
/// <summary>
/// 删除对于TopBasePoco进行物理删除对于PersistPoco把IsValid修改为false
/// </summary>
void DoDelete();
Task DoDeleteAsync();
/// <summary>
/// 彻底删除对PersistPoco进行物理删除
/// </summary>
void DoRealDelete();
Task DoRealDeleteAsync();
/// <summary>
/// 将源VM的上数据库上下文Session登录用户信息模型状态信息缓存信息等内容复制到本VM中
/// </summary>
/// <param name="vm">复制的源</param>
void CopyContext(BaseVM vm);
/// <summary>
/// 是否跳过基类的唯一性验证,批量导入的时候唯一性验证会由存储过程完成,不需要单独调用本类的验证方法
/// </summary>
bool ByPassBaseValidation { get; set; }
void Validate();
IModelStateService MSD { get; }
}
/// <summary>
/// 单表增删改查基类所有单表操作的VM应该继承这个基类
/// </summary>
/// <typeparam name="TModel">继承TopBasePoco的类</typeparam>
public class BaseCRUDVM<TModel> : BaseVM, IBaseCRUDVM<TModel> where TModel : TopBasePoco, new()
{
public TModel Entity { get; set; }
[JsonIgnore]
public bool ByPassBaseValidation { get; set; }
//保存读取时Include的内容
private List<Expression<Func<TModel, object>>> _toInclude { get; set; }
/// <summary>
/// 构造函数
/// </summary>
public BaseCRUDVM()
{
//初始化Entity
var ctor = typeof(TModel).GetConstructor(Type.EmptyTypes);
Entity = ctor.Invoke(null) as TModel;
//初始化VM中所有List<>的类
//var lists = typeof(TModel).GetAllProperties().Where(x => x.PropertyType.IsGeneric(typeof(List<>)));
//foreach (var li in lists)
//{
// var gs = li.PropertyType.GetGenericArguments();
// var newObj = Activator.CreateInstance(typeof(List<>).MakeGenericType(gs[0]));
// li.SetValue(Entity, newObj, null);
//}
}
public IQueryable<TModel> GetBaseQuery()
{
return DC.Set<TModel>();
}
/// <summary>
/// 设定添加和修改时对于重复数据的判断,子类进行相关操作时应重载这个函数
/// </summary>
/// <returns>唯一性属性</returns>
public virtual DuplicatedInfo<TModel> SetDuplicatedCheck()
{
return null;
}
/// <summary>
/// 设定读取是Include的内容
/// </summary>
/// <param name="exps">需要关联的类</param>
public void SetInclude(params Expression<Func<TModel, object>>[] exps)
{
_toInclude = _toInclude ?? new List<Expression<Func<TModel, object>>>();
_toInclude.AddRange(exps);
}
/// <summary>
/// 根据主键Id设定Entity
/// </summary>
/// <param name="id">主键Id</param>
public void SetEntityById(object id)
{
this.Entity = GetById(id);
}
/// <summary>
/// 设置Entity
/// </summary>
/// <param name="entity">要设定的TopBasePoco</param>
public void SetEntity(object entity)
{
this.Entity = entity as TModel;
}
/// <summary>
/// 根据主键获取Entity
/// </summary>
/// <param name="Id">主键Id</param>
/// <returns>Entity</returns>
protected virtual TModel GetById(object Id)
{
TModel rv = null;
//建立基础查询
var query = DC.Set<TModel>().AsQueryable();
//循环添加其他设定的Include
if (_toInclude != null)
{
foreach (var item in _toInclude)
{
query = query.Include(item);
}
}
if (typeof(IPersistPoco).IsAssignableFrom(typeof(TModel)))
{
var mod = new IsValidModifier();
var newExp = mod.Modify(query.Expression);
query = query.Provider.CreateQuery<TModel>(newExp) as IOrderedQueryable<TModel>;
}
//获取数据
rv = query.CheckID(Id).AsNoTracking().SingleOrDefault();
if (rv == null)
{
throw new Exception("数据不存在");
}
//如果TopBasePoco有关联的附件则自动Include 附件名称
var pros = typeof(TModel).GetAllProperties();
var fa = pros.Where(x => x.PropertyType == typeof(FileAttachment)).ToList();
foreach (var f in fa)
{
var fname = DC.GetFKName2<TModel>(f.Name);
var fid = typeof(TModel).GetSingleProperty(fname).GetValue(rv);
if (fid != null && Wtm.ServiceProvider != null)
{
var fp = Wtm.ServiceProvider.GetRequiredService<WtmFileProvider>();
var file = fp.GetFile(fid?.ToString(), false, DC);
rv.SetPropertyValue(f.Name, file);
}
}
return rv;
}
/// <summary>
/// 添加,进行默认的添加操作。子类如有自定义操作应重载本函数
/// </summary>
public virtual void DoAdd()
{
DoAddPrepare();
//删除不需要的附件
if (DeletedFileIds != null && DeletedFileIds.Count > 0 && Wtm.ServiceProvider != null)
{
var fp = Wtm.ServiceProvider.GetRequiredService<WtmFileProvider>();
foreach (var item in DeletedFileIds)
{
fp.DeleteFile(item.ToString(), DC);
}
}
DC.SaveChanges();
}
public virtual async Task DoAddAsync()
{
DoAddPrepare();
//删除不需要的附件
if (DeletedFileIds != null && DeletedFileIds.Count > 0 && Wtm.ServiceProvider != null)
{
var fp = Wtm.ServiceProvider.GetRequiredService<WtmFileProvider>();
foreach (var item in DeletedFileIds)
{
fp.DeleteFile(item.ToString(), DC.ReCreate());
}
}
await DC.SaveChangesAsync();
}
private void DoAddPrepare()
{
var pros = typeof(TModel).GetAllProperties();
//将所有TopBasePoco的属性赋空值防止添加关联的重复内容
if (typeof(TModel) != typeof(FileAttachment))
{
foreach (var pro in pros)
{
if (pro.PropertyType.GetTypeInfo().IsSubclassOf(typeof(TopBasePoco)))
{
pro.SetValue(Entity, null);
}
}
}
//自动设定添加日期和添加人
if (typeof(IBasePoco).IsAssignableFrom(typeof(TModel)))
{
IBasePoco ent = Entity as IBasePoco;
if (ent.CreateTime == null)
{
ent.CreateTime = DateTime.Now;
}
if (string.IsNullOrEmpty(ent.CreateBy))
{
ent.CreateBy = LoginUserInfo?.ITCode;
}
}
if (typeof(IPersistPoco).IsAssignableFrom(typeof(TModel)))
{
(Entity as IPersistPoco).IsValid = true;
}
#region
foreach (var pro in pros)
{
//找到类型为List<xxx>的字段
if (pro.PropertyType.GenericTypeArguments.Count() > 0)
{
//获取xxx的类型
var ftype = pro.PropertyType.GenericTypeArguments.First();
//如果xxx继承自TopBasePoco
if (ftype.IsSubclassOf(typeof(TopBasePoco)))
{
//界面传过来的子表数据
IEnumerable<TopBasePoco> list = pro.GetValue(Entity) as IEnumerable<TopBasePoco>;
if (list != null && list.Count() > 0)
{
string fkname = DC.GetFKName<TModel>(pro.Name);
var itemPros = ftype.GetAllProperties();
bool found = false;
foreach (var newitem in list)
{
foreach (var itempro in itemPros)
{
if (itempro.PropertyType.IsSubclassOf(typeof(TopBasePoco)))
{
itempro.SetValue(newitem, null);
}
if (!string.IsNullOrEmpty(fkname))
{
if (itempro.Name.ToLower() == fkname.ToLower())
{
try
{
itempro.SetValue(newitem, Entity.GetID());
found = true;
}
catch { }
}
}
}
}
//如果没有找到相应的外建字段,则可能是多对多的关系,或者做了特殊的设定,这种情况框架无法支持,直接退出本次循环
if (found == false)
{
continue;
}
//循环页面传过来的子表数据,自动设定添加日期和添加人
foreach (var newitem in list)
{
var subtype = newitem.GetType();
if (typeof(IBasePoco).IsAssignableFrom(subtype))
{
IBasePoco ent = newitem as IBasePoco;
if (ent.CreateTime == null)
{
ent.CreateTime = DateTime.Now;
}
if (string.IsNullOrEmpty(ent.CreateBy))
{
ent.CreateBy = LoginUserInfo?.ITCode;
}
}
}
}
}
}
}
#endregion
//添加数据
DC.Set<TModel>().Add(Entity);
}
/// <summary>
/// 修改,进行默认的修改操作。子类如有自定义操作应重载本函数
/// </summary>
/// <param name="updateAllFields">为true时框架会更新当前Entity的全部值为false时框架会检查Request.Form里的key只更新表单提交的字段</param>
public virtual void DoEdit(bool updateAllFields = false)
{
DoEditPrepare(updateAllFields);
try
{
DC.SaveChanges();
}
catch
{
MSD.AddModelError(" ", Localizer["Sys.EditFailed"]);
}
//删除不需要的附件
if (DeletedFileIds != null && DeletedFileIds.Count > 0 && Wtm.ServiceProvider != null)
{
var fp = Wtm.ServiceProvider.GetRequiredService<WtmFileProvider>();
foreach (var item in DeletedFileIds)
{
fp.DeleteFile(item.ToString(), DC.ReCreate());
}
}
}
public virtual async Task DoEditAsync(bool updateAllFields = false)
{
DoEditPrepare(updateAllFields);
await DC.SaveChangesAsync();
//删除不需要的附件
if (DeletedFileIds != null && DeletedFileIds.Count > 0 && Wtm.ServiceProvider != null)
{
var fp = Wtm.ServiceProvider.GetRequiredService<WtmFileProvider>();
foreach (var item in DeletedFileIds)
{
fp.DeleteFile(item.ToString(), DC);
}
}
}
private void DoEditPrepare(bool updateAllFields)
{
if (typeof(IBasePoco).IsAssignableFrom(typeof(TModel)))
{
IBasePoco ent = Entity as IBasePoco;
//if (ent.UpdateTime == null)
//{
ent.UpdateTime = DateTime.Now;
//}
//if (string.IsNullOrEmpty(ent.UpdateBy))
//{
ent.UpdateBy = LoginUserInfo?.ITCode;
//}
}
var pros = typeof(TModel).GetAllProperties();
pros = pros.Where(x => x.CustomAttributes.Any(y => y.AttributeType == typeof(NotMappedAttribute)) == false).ToList();
if (typeof(TModel) != typeof(FileAttachment))
{
foreach (var pro in pros)
{
if (pro.PropertyType.GetTypeInfo().IsSubclassOf(typeof(TopBasePoco)))
{
pro.SetValue(Entity, null);
}
}
}
#region
foreach (var pro in pros)
{
//找到类型为List<xxx>的字段
if (pro.PropertyType.GenericTypeArguments.Count() > 0)
{
//获取xxx的类型
var ftype = pro.PropertyType.GenericTypeArguments.First();
//如果xxx继承自TopBasePoco
if (ftype.IsSubclassOf(typeof(TopBasePoco)))
{
//界面传过来的子表数据
if (pro.GetValue(Entity) is IEnumerable<TopBasePoco> list && list.Count() > 0)
{
//获取外键字段名称
string fkname = DC.GetFKName<TModel>(pro.Name);
var itemPros = ftype.GetAllProperties();
bool found = false;
foreach (var newitem in list)
{
var subtype = newitem.GetType();
if (typeof(IBasePoco).IsAssignableFrom(subtype))
{
IBasePoco ent = newitem as IBasePoco;
if (ent.UpdateTime == null)
{
ent.UpdateTime = DateTime.Now;
}
if (string.IsNullOrEmpty(ent.UpdateBy))
{
ent.UpdateBy = LoginUserInfo?.ITCode;
}
}
//循环页面传过来的子表数据,将关联到TopBasePoco的字段设为null,并且把外键字段的值设定为主表ID
foreach (var itempro in itemPros)
{
if (itempro.PropertyType.IsSubclassOf(typeof(TopBasePoco)))
{
itempro.SetValue(newitem, null);
}
if (!string.IsNullOrEmpty(fkname))
{
if (itempro.Name.ToLower() == fkname.ToLower())
{
itempro.SetValue(newitem, Entity.GetID());
found = true;
}
}
}
}
//如果没有找到相应的外建字段,则可能是多对多的关系,或者做了特殊的设定,这种情况框架无法支持,直接退出本次循环
if (found == false)
{
continue;
}
TModel _entity = null;
//打开新的数据库联接,获取数据库中的主表和子表数据
//using (var ndc = DC.CreateNew())
//{
_entity = DC.Set<TModel>().Include(pro.Name).AsNoTracking().CheckID(Entity.GetID()).FirstOrDefault();
//}
if (_entity == null)
{
MSD.AddModelError(" ", Localizer["Sys.EditFailed"]);
return;
}
//比较子表原数据和新数据的区别
IEnumerable<TopBasePoco> toadd = null;
IEnumerable<TopBasePoco> toremove = null;
IEnumerable<TopBasePoco> data = _entity.GetType().GetSingleProperty(pro.Name).GetValue(_entity) as IEnumerable<TopBasePoco>;
Utils.CheckDifference(data, list, out toremove, out toadd);
//设定子表应该更新的字段
List<string> setnames = new List<string>();
foreach (var field in FC.Keys)
{
var f = field.ToLower();
if (f.StartsWith("entity." + pro.Name.ToLower() + "[0]."))
{
string name = f.Replace("entity." + pro.Name.ToLower() + "[0].", "");
setnames.Add(name);
}
}
//前台传过来的数据
foreach (var newitem in list)
{
//数据库中的数据
foreach (var item in data)
{
//需要更新的数据
if (newitem.GetID().ToString() == item.GetID().ToString())
{
dynamic i = newitem;
var newitemType = item.GetType();
foreach (var itempro in itemPros)
{
if (!itempro.PropertyType.IsSubclassOf(typeof(TopBasePoco)) && (updateAllFields == true || setnames.Contains(itempro.Name.ToLower())))
{
var notmapped = itempro.GetCustomAttribute<NotMappedAttribute>();
if (itempro.Name != "ID" && notmapped == null && itempro.PropertyType.IsList() == false)
{
DC.UpdateProperty(i, itempro.Name);
}
}
}
if (typeof(IBasePoco).IsAssignableFrom(item.GetType()))
{
DC.UpdateProperty(i, "UpdateTime");
DC.UpdateProperty(i, "UpdateBy");
}
}
}
}
//需要删除的数据
foreach (var item in toremove)
{
//如果是PersistPoco则把IsValid设为false并不进行物理删除
if (typeof(IPersistPoco).IsAssignableFrom(ftype))
{
(item as IPersistPoco).IsValid = false;
if (typeof(IBasePoco).IsAssignableFrom(ftype))
{
(item as IBasePoco).UpdateTime = DateTime.Now;
(item as IBasePoco).UpdateBy = LoginUserInfo?.ITCode;
}
dynamic i = item;
DC.UpdateEntity(i);
}
else
{
foreach (var itempro in itemPros)
{
if (itempro.PropertyType.IsSubclassOf(typeof(TopBasePoco)))
{
itempro.SetValue(item, null);
}
}
dynamic i = item;
DC.DeleteEntity(i);
}
}
//需要添加的数据
foreach (var item in toadd)
{
if (typeof(IBasePoco).IsAssignableFrom(item.GetType()))
{
IBasePoco ent = item as IBasePoco;
if (ent.CreateTime == null)
{
ent.CreateTime = DateTime.Now;
}
if (string.IsNullOrEmpty(ent.CreateBy))
{
ent.CreateBy = LoginUserInfo?.ITCode;
}
}
DC.AddEntity(item);
}
}
else if ((pro.GetValue(Entity) is IEnumerable<TopBasePoco> list2 && list2?.Count() == 0))
{
var itemPros = ftype.GetAllProperties();
var _entity = DC.Set<TModel>().Include(pro.Name).AsNoTracking().CheckID(Entity.GetID()).FirstOrDefault();
if (_entity != null)
{
IEnumerable<TopBasePoco> removeData = _entity.GetType().GetSingleProperty(pro.Name).GetValue(_entity) as IEnumerable<TopBasePoco>;
//如果是PersistPoco则把IsValid设为false并不进行物理删除
if (removeData is IEnumerable<IPersistPoco> removePersistPocoData)
{
foreach (var item in removePersistPocoData)
{
(item as IPersistPoco).IsValid = false;
if (typeof(IBasePoco).IsAssignableFrom(item.GetType()))
{
(item as IBasePoco).UpdateTime = DateTime.Now;
(item as IBasePoco).UpdateBy = LoginUserInfo?.ITCode;
}
dynamic i = item;
DC.UpdateEntity(i);
}
}
else
{
foreach (var item in removeData)
{
foreach (var itempro in itemPros)
{
if (itempro.PropertyType.IsSubclassOf(typeof(TopBasePoco)))
{
itempro.SetValue(item, null);
}
}
dynamic i = item;
DC.DeleteEntity(i);
}
}
}
}
}
}
}
#endregion
if (updateAllFields == false)
{
foreach (var field in FC.Keys)
{
var f = field.ToLower();
if (f.StartsWith("entity.") && !f.Contains("["))
{
string name = f.Replace("entity.", "");
try
{
DC.UpdateProperty(Entity, pros.Where(x => x.Name.ToLower() == name).Select(x => x.Name).FirstOrDefault());
}
catch (Exception)
{
}
}
}
if (typeof(IBasePoco).IsAssignableFrom(typeof(TModel)))
{
try
{
DC.UpdateProperty(Entity, "UpdateTime");
DC.UpdateProperty(Entity, "UpdateBy");
}
catch (Exception)
{
}
}
}
else
{
DC.UpdateEntity(Entity);
}
}
/// <summary>
/// 删除,进行默认的删除操作。子类如有自定义操作应重载本函数
/// </summary>
public virtual void DoDelete()
{
//如果是PersistPoco则把IsValid设为false并不进行物理删除
if (typeof(IPersistPoco).IsAssignableFrom(typeof(TModel)))
{
FC.Add("Entity.IsValid", 0);
(Entity as IPersistPoco).IsValid = false;
var pros = typeof(TModel).GetAllProperties();
//如果包含List<PersistPoco>将子表IsValid也设置为false
var fas = pros.Where(x => typeof(IEnumerable<IPersistPoco>).IsAssignableFrom(x.PropertyType)).ToList();
foreach (var f in fas)
{
f.SetValue(Entity, f.PropertyType.GetConstructor(Type.EmptyTypes).Invoke(null));
}
DoEditPrepare(false);
DC.SaveChanges();
}
//如果是普通的TopBasePoco则进行物理删除
else if (typeof(TModel).GetTypeInfo().IsSubclassOf(typeof(TopBasePoco)))
{
DoRealDelete();
}
}
public virtual async Task DoDeleteAsync()
{
//如果是PersistPoco则把IsValid设为false并不进行物理删除
if (typeof(IPersistPoco).IsAssignableFrom(typeof(TModel)))
{
FC.Add("Entity.IsValid", 0);
(Entity as IPersistPoco).IsValid = false;
var pros = typeof(TModel).GetAllProperties();
//如果包含List<PersistPoco>将子表IsValid也设置为false
var fas = pros.Where(x => typeof(IEnumerable<IPersistPoco>).IsAssignableFrom(x.PropertyType)).ToList();
foreach (var f in fas)
{
f.SetValue(Entity, f.PropertyType.GetConstructor(Type.EmptyTypes).Invoke(null));
}
fas = pros.Where(x => typeof(TopBasePoco).IsAssignableFrom(x.PropertyType)).ToList();
foreach (var f in fas)
{
f.SetValue(Entity, null);
}
DoEditPrepare(false);
try
{
await DC.SaveChangesAsync();
}
catch (DbUpdateException)
{
MSD.AddModelError("", CoreProgram._localizer?["Sys.DeleteFailed"]);
}
}
//如果是普通的TopBasePoco则进行物理删除
else if (typeof(TModel).GetTypeInfo().IsSubclassOf(typeof(TopBasePoco)))
{
DoRealDelete();
}
}
/// <summary>
/// 物理删除对于普通的TopBasePoco和Delete操作相同对于PersistPoco则进行真正的删除。子类如有自定义操作应重载本函数
/// </summary>
public virtual void DoRealDelete()
{
try
{
List<Guid> fileids = new List<Guid>();
var pros = typeof(TModel).GetAllProperties();
//如果包含附件,则先删除附件
var fa = pros.Where(x => x.PropertyType == typeof(FileAttachment) || typeof(TopBasePoco).IsAssignableFrom(x.PropertyType)).ToList();
foreach (var f in fa)
{
if (f.GetValue(Entity) is FileAttachment file)
{
fileids.Add(file.ID);
}
f.SetValue(Entity, null);
}
var fas = pros.Where(x => typeof(IEnumerable<ISubFile>).IsAssignableFrom(x.PropertyType)).ToList();
foreach (var f in fas)
{
var subs = f.GetValue(Entity) as IEnumerable<ISubFile>;
if (subs == null)
{
var fullEntity = DC.Set<TModel>().AsQueryable().Include(f.Name).AsNoTracking().CheckID(Entity.ID).FirstOrDefault();
subs = f.GetValue(fullEntity) as IEnumerable<ISubFile>;
}
if (subs != null)
{
foreach (var sub in subs)
{
fileids.Add(sub.FileId);
}
f.SetValue(Entity, null);
}
}
if (typeof(TModel) != typeof(FileAttachment))
{
foreach (var pro in pros)
{
if (pro.PropertyType.GetTypeInfo().IsSubclassOf(typeof(TopBasePoco)))
{
pro.SetValue(Entity, null);
}
}
}
DC.DeleteEntity(Entity);
DC.SaveChanges();
if (Wtm.ServiceProvider != null)
{
var fp = Wtm.ServiceProvider.GetRequiredService<WtmFileProvider>();
foreach (var item in fileids)
{
fp.DeleteFile(item.ToString(), DC.ReCreate());
}
}
}
catch (Exception)
{
MSD.AddModelError("", CoreProgram._localizer?["Sys.DeleteFailed"]);
}
}
public virtual async Task DoRealDeleteAsync()
{
try
{
List<Guid> fileids = new List<Guid>();
var pros = typeof(TModel).GetAllProperties();
//如果包含附件,则先删除附件
var fa = pros.Where(x => x.PropertyType == typeof(FileAttachment) || typeof(TopBasePoco).IsAssignableFrom(x.PropertyType)).ToList();
foreach (var f in fa)
{
if (f.GetValue(Entity) is FileAttachment file)
{
fileids.Add(file.ID);
}
f.SetValue(Entity, null);
}
var fas = pros.Where(x => typeof(IEnumerable<ISubFile>).IsAssignableFrom(x.PropertyType)).ToList();
foreach (var f in fas)
{
var subs = f.GetValue(Entity) as IEnumerable<ISubFile>;
foreach (var sub in subs)
{
fileids.Add(sub.FileId);
}
f.SetValue(Entity, null);
}
if (typeof(TModel) != typeof(FileAttachment))
{
foreach (var pro in pros)
{
if (pro.PropertyType.GetTypeInfo().IsSubclassOf(typeof(TopBasePoco)))
{
pro.SetValue(Entity, null);
}
}
}
DC.DeleteEntity(Entity);
await DC.SaveChangesAsync();
if (Wtm.ServiceProvider != null)
{
var fp = Wtm.ServiceProvider.GetRequiredService<WtmFileProvider>();
foreach (var item in fileids)
{
fp.DeleteFile(item.ToString(), DC.ReCreate());
}
}
}
catch (Exception)
{
MSD.AddModelError("", CoreProgram._localizer?["Sys.DeleteFailed"]);
}
}
/// <summary>
/// 创建重复数据信息
/// </summary>
/// <param name="FieldExps">重复数据信息</param>
/// <returns>重复数据信息</returns>
protected DuplicatedInfo<TModel> CreateFieldsInfo(params DuplicatedField<TModel>[] FieldExps)
{
DuplicatedInfo<TModel> d = new DuplicatedInfo<TModel>();
d.AddGroup(FieldExps);
return d;
}
/// <summary>
/// 创建一个简单重复数据信息
/// </summary>
/// <param name="FieldExp">重复数据的字段</param>
/// <returns>重复数据信息</returns>
public static DuplicatedField<TModel> SimpleField(Expression<Func<TModel, object>> FieldExp)
{
return new DuplicatedField<TModel>(FieldExp);
}
/// <summary>
/// 创建一个关联到其他表数组中数据的重复信息
/// </summary>
/// <typeparam name="V">关联表类</typeparam>
/// <param name="MiddleExp">指向关联表类数组的Lambda</param>
/// <param name="FieldExps">指向最终字段的Lambda</param>
/// <returns>重复数据信息</returns>
public static DuplicatedField<TModel> SubField<V>(Expression<Func<TModel, List<V>>> MiddleExp, params Expression<Func<V, object>>[] FieldExps)
{
return new ComplexDuplicatedField<TModel, V>(MiddleExp, FieldExps);
}
/// <summary>
/// 验证数据,默认验证重复数据。子类如需要其他自定义验证,则重载这个函数
/// </summary>
/// <returns>验证结果</returns>
public override void Validate()
{
if (ByPassBaseValidation == false)
{
base.Validate();
////如果msd是BasicMSD则认为他是手动创建的也就是说并没有走asp.net core默认的模型验证
////那么手动验证模型
//if (Wtm?.MSD is BasicMSD)
//{
// var valContext = new ValidationContext(this.Entity);
// List<ValidationResult> error = new List<ValidationResult>();
// if (!Validator.TryValidateObject(Entity, valContext, error, true))
// {
// foreach (var item in error)
// {
// string key = item.MemberNames.FirstOrDefault();
// if (MSD.Keys.Contains(key) == false)
// {
// MSD.AddModelError($"Entity.{key}", item.ErrorMessage);
// }
// }
// }
// var list = typeof(TModel).GetAllProperties().Where(x => x.PropertyType.IsListOf<TopBasePoco>());
// foreach (var item in list)
// {
// var it = item.GetValue(Entity) as IEnumerable;
// if(it == null)
// {
// continue;
// }
// var contextset = false;
// foreach (var e in it)
// {
// if(contextset == false)
// {
// valContext = new ValidationContext(e);
// contextset = true;
// }
// if (!Validator.TryValidateObject(e, valContext, error, true))
// {
// foreach (var err in error)
// {
// string key = err.MemberNames.FirstOrDefault();
// if (MSD.Keys.Contains(key) == false)
// {
// MSD.AddModelError($"Entity.{item.Name}.{key}", err.ErrorMessage);
// }
// }
// }
// }
// }
//}
//验证重复数据
ValidateDuplicateData();
}
}
/// <summary>
/// 验证重复数据
/// 如果存在重复的数据则返回已存在数据的id列表
/// 如果不存在重复数据,则返回一个空列表
/// </summary>
protected List<object> ValidateDuplicateData()
{
//定义一个对象列表用于存放重复数据的id
var count = new List<object>();
//获取设定的重复字段信息
var checkCondition = SetDuplicatedCheck();
if (checkCondition != null && checkCondition.Groups.Count > 0)
{
//生成基础Query
var baseExp = DC.Set<TModel>().AsQueryable();
var modelType = typeof(TModel);
ParameterExpression para = Expression.Parameter(modelType, "tm");
//循环所有重复字段组
foreach (var group in checkCondition.Groups)
{
var innercount = new List<object>();
List<Expression> conditions = new List<Expression>();
//生成一个表达式,类似于 x=>x.Id != id这是为了当修改数据时验证重复性的时候排除当前正在修改的数据
var idproperty = typeof(TModel).GetSingleProperty("ID");
MemberExpression idLeft = Expression.Property(para, idproperty);
ConstantExpression idRight = Expression.Constant(Entity.GetID());
BinaryExpression idNotEqual = Expression.NotEqual(idLeft, idRight);
conditions.Add(idNotEqual);
List<PropertyInfo> props = new List<PropertyInfo>();
//在每个组中循环所有字段
foreach (var field in group.Fields)
{
Expression exp = field.GetExpression(Entity, para);
if (exp != null)
{
conditions.Add(exp);
}
//将字段名保存,为后面生成错误信息作准备
props.AddRange(field.GetProperties());
}
//如果要求判断id不重复则去掉id不相等的判断加入id相等的判断
if (props.Any(x => x.Name.ToLower() == "id"))
{
conditions.RemoveAt(0);
BinaryExpression idEqual = Expression.Equal(idLeft, idRight);
conditions.Insert(0, idEqual);
}
//int count = 0;
if (conditions.Count > 1)
{
//循环添加条件并生成Where语句
//Expression conExp = conditions[0];
Expression whereCallExpression = baseExp.Expression;
for (int i = 0; i < conditions.Count; i++)
{
whereCallExpression = Expression.Call(
typeof(Queryable),
"Where",
new Type[] { modelType },
whereCallExpression,
Expression.Lambda<Func<TModel, bool>>(conditions[i], new ParameterExpression[] { para }));
}
var result = baseExp.Provider.CreateQuery(whereCallExpression);
foreach (TopBasePoco res in result)
{
var id = res.GetID();
count.Add(id);
innercount.Add(id);
}
}
if (innercount.Count > 0)
{
//循环拼接所有字段名
string AllName = "";
foreach (var prop in props)
{
string name = PropertyHelper.GetPropertyDisplayName(prop);
AllName += name + ",";
}
if (AllName.EndsWith(","))
{
AllName = AllName.Remove(AllName.Length - 1);
}
//如果只有一个字段重复,则拼接形成 xxx字段重复 这种提示
if (props.Count == 1)
{
MSD.AddModelError(GetValidationFieldName(props[0])[0], CoreProgram._localizer?["Sys.DuplicateError", AllName]);
}
//如果多个字段重复,则拼接形成 xxyyzz组合字段重复 这种提示
else if (props.Count > 1)
{
MSD.AddModelError(GetValidationFieldName(props.First())[0], CoreProgram._localizer?["Sys.DuplicateGroupError", AllName]);
}
}
}
}
return count;
}
/// <summary>
/// 根据属性信息获取验证字段名
/// </summary>
/// <param name="pi">属性信息</param>
/// <returns>验证字段名称数组用于ValidationResult</returns>
private string[] GetValidationFieldName(PropertyInfo pi)
{
return new[] { "Entity." + pi.Name };
}
}
}