/// <summary> /// 判断用户是否有指定数据的所有权 /// 如果部分数据不存在,会返回false /// </summary> /// <typeparam name="TData">数据类型</typeparam> /// <param name="userId">用户Id</param> /// <param name="ids">数据Id列表</param> /// <returns></returns> public virtual bool HasOwnership <TData>(long userId, IList <object> ids) where TData : class, IEntity { // 检查数据类型是否有所属用户 var userOwnedTrait = UserOwnedTrait.For <TData>(); if (!userOwnedTrait.IsUserOwned) { throw new ArgumentException(string.Format("type {0} not user owned", typeof(TData).Name)); } // 构建表达式 (data => ids.Contains(data.Id) && data.Owner.Id == userId) var entityTrait = EntityTrait.For <TData>(); var userEntityTrait = EntityTrait.For <User>(); var dataParam = Expression.Parameter(typeof(TData), "data"); var body = Expression.AndAlso( Expression.Call( IListContainsMethodInfo.Value, Expression.Constant(ids.Select(id => id.ConvertOrDefault(entityTrait.PrimaryKeyType, null)).ToList()), Expression.Convert( Expression.Property(dataParam, entityTrait.PrimaryKey), typeof(object))), Expression.Equal( Expression.Property( Expression.Property(dataParam, userOwnedTrait.PropertyName), userEntityTrait.PrimaryKey), Expression.Constant(userId))); var count = UnitOfWork.ReadData <TData, long>(r => { return(r.Count(Expression.Lambda <Func <TData, bool> >(body, dataParam))); }); return(count == ids.Count); }
/// <summary> /// 获取指定Id的单个对象,找不到时返回null /// </summary> /// <param name="id">数据Id</param> /// <returns></returns> public virtual TData GetById(object id) { var trait = EntityTrait.For <TData>(); return(Get(ExpressionUtils.MakeMemberEqualiventExpression <TData>( trait.PrimaryKey, id.ConvertOrDefault(trait.PrimaryKeyType, null)))); }
/// <summary> /// 批量永久删除 /// 返回删除的数量 /// 这个函数会把数据从数据库中删除 /// </summary> /// <param name="ids">Id列表</param> /// <returns></returns> public virtual long BatchDeleteForever(IEnumerable <object> ids) { var databaseManager = Application.Ioc.Resolve <DatabaseManager>(); var trait = EntityTrait.For <TData>(); long count = 0; foreach (var id in ids) { count += Context.BatchDelete( ExpressionUtils.MakeMemberEqualiventExpression <TData>( trait.PrimaryKey, id.ConvertOrDefault(trait.PrimaryKeyType, null))); } return(count); }
/// <summary> /// 按所属用户等于指定用户过滤数据 /// </summary> /// <typeparam name="TData">数据类型</typeparam> /// <param name="query">查询对象</param> /// <param name="userId">用户Id</param> /// <returns></returns> public static IQueryable <TData> FilterByOwnedUser <TData>( this IQueryable <TData> query, long userId) { // 构建表达式 (data => data.Owner.Id == userId) var userOwnedTrait = UserOwnedTrait.For <TData>(); var userEntityTrait = EntityTrait.For <User>(); var dataParam = Expression.Parameter(typeof(TData), "data"); var body = Expression.Equal( Expression.Property( Expression.Property(dataParam, userOwnedTrait.PropertyName), userEntityTrait.PrimaryKey), Expression.Constant(userId)); return(query.Where(Expression.Lambda <Func <TData, bool> >(body, dataParam))); }
/// <summary> /// 添加删除按钮 /// 点击后弹出确认框,确认后把json=[数据Id]提交到删除url /// </summary> /// <param name="column">操作列</param> /// <param name="typeName">类型名称</param> /// <param name="deleteUrl">删除使用的Url</param> /// <param name="name">名称,不指定时使用默认值</param> /// <param name="buttonClass">按钮的Css类,不指定时使用默认值</param> /// <param name="iconClass">图标的Css类,不指定时使用默认值</param> /// <param name="titleTemplate">标题的模板,格式是underscore.js的格式,参数传入rows</param> /// <param name="urlTemplate">编辑Url的模板,格式是underscore.js的格式,参数传入rows</param> /// <param name="primaryKey">数据Id保存的名称,不指定时使用默认值</param> /// <param name="dialogParameters">弹出框的参数,不指定时使用默认值</param> public static void AddDeleteAction( this AjaxTableActionColumn column, string typeName, string deleteUrl, string name = null, string buttonClass = null, string iconClass = null, string titleTemplate = null, string urlTemplate = null, string primaryKey = null, object dialogParameters = null) { primaryKey = primaryKey ?? EntityTrait.For <object>().PrimaryKey; column.AddConfirmActionForBelongedRow( name ?? new T("Delete"), buttonClass ?? "btn btn-xs btn-danger", iconClass ?? "fa fa-remove", titleTemplate ?? string.Format(new T("Delete {0}"), new T(typeName)), ScriptStrings.ConfirmMessageTemplateForMultiSelected( string.Format(new T("Sure to delete following {0}?"), new T(typeName)), "ToString"), ScriptStrings.PostConfirmedActionForMultiSelected(primaryKey, deleteUrl), dialogParameters); }
/// <summary> /// 获取指定Id的单个对象,找不到或标记已删除时返回null /// </summary> /// <param name="id">数据Id</param> /// <returns></returns> public virtual TData GetByIdWhereNotDeleted(object id) { // 判断类型是否可回收 var entityTrait = EntityTrait.For <TData>(); var recyclableTrait = RecyclableTrait.For <TData>(); if (!recyclableTrait.IsRecyclable) { throw new ArgumentException(string.Format("entity {0} not recyclable", typeof(TData).Name)); } // 构建表达式 (data => data.Id == id && !data.Deleted) var dataParam = Expression.Parameter(typeof(TData), "data"); var body = Expression.AndAlso( Expression.Equal( Expression.Property(dataParam, entityTrait.PrimaryKey), Expression.Constant(id.ConvertOrDefault(entityTrait.PrimaryKeyType, null))), Expression.Not(Expression.Property(dataParam, recyclableTrait.PropertyName))); return(Get(Expression.Lambda <Func <TData, bool> >(body, dataParam))); }
/// <summary> /// 批量恢复 /// 返回恢复的数量 /// </summary> /// <param name="ids">Id列表</param> /// <returns></returns> public virtual long BatchRecover(IEnumerable <object> ids) { var databaseManager = Application.Ioc.Resolve <DatabaseManager>(); var propertyName = RecyclableTrait.For <TData>().PropertyName; var setter = ReflectionUtils.MakeSetter <TData, bool>(propertyName); var trait = EntityTrait.For <TData>(); long count = 0; foreach (var id in ids) { var data = Context.Get( ExpressionUtils.MakeMemberEqualiventExpression <TData>( trait.PrimaryKey, id.ConvertOrDefault(trait.PrimaryKeyType, null))); if (data != null) { Context.Save(ref data, d => setter(d, false)); ++count; } } return(count); }
/// <summary> /// 添加删除相关的按钮 /// 如果数据类型可以回收,则添加批量删除或批量恢复和永久删除 /// 如果数据类型不可以回收,则添加批量永久删除 /// </summary> /// <param name="column">Id列</param> /// <param name="request">搜索请求</param> /// <param name="dataType">数据类型</param> /// <param name="typeName">类型名称</param> /// <param name="batchUrl">批量操作使用的Url</param> public static void AddDeleteActions( this AjaxTableIdColumn column, AjaxTableSearchRequest request, Type dataType, string typeName, string batchUrl) { // 判断需要添加哪些操作 bool addBatchDelete = false; bool addBatchRecover = false; bool addBatchDeleteForever = false; if (RecyclableTrait.For(dataType).IsRecyclable) { var deleted = request.Conditions.GetOrDefault <bool>("Deleted"); addBatchDelete = !deleted; addBatchRecover = deleted; addBatchDeleteForever = deleted; } else { addBatchDeleteForever = true; } // 添加批量删除 typeName = new T(typeName); var entityTrait = EntityTrait.For(dataType); if (addBatchDelete) { column.AddConfirmActionForMultiChecked( new T("Batch Delete"), "fa fa-recycle", string.Format(new T("Please select {0} to delete"), typeName), new T("Batch Delete"), ScriptStrings.ConfirmMessageTemplateForMultiSelected( string.Format(new T("Sure to delete following {0}?"), typeName), "ToString"), ScriptStrings.PostConfirmedActionForMultiSelected( entityTrait.PrimaryKey, batchUrl + "?action=delete"), new { type = "type-danger" }); } // 添加批量恢复 if (addBatchRecover) { column.AddConfirmActionForMultiChecked( new T("Batch Recover"), "fa fa-history", string.Format(new T("Please select {0} to recover"), typeName), new T("Batch Recover"), ScriptStrings.ConfirmMessageTemplateForMultiSelected( string.Format(new T("Sure to recover following {0}?"), typeName), "ToString"), ScriptStrings.PostConfirmedActionForMultiSelected( entityTrait.PrimaryKey, batchUrl + "?action=recover")); } // 添加批量永久删除 if (addBatchDeleteForever) { column.AddConfirmActionForMultiChecked( new T("Batch Delete Forever"), "fa fa-remove", string.Format(new T("Please select {0} to delete"), typeName), new T("Batch Delete Forever"), ScriptStrings.ConfirmMessageTemplateForMultiSelected( string.Format(new T("Sure to delete following {0} forever?"), typeName), "ToString"), ScriptStrings.PostConfirmedActionForMultiSelected( entityTrait.PrimaryKey, batchUrl + "?action=delete_forever"), new { type = "type-danger" }); } }