一直有关注CSLA框架,最近闲来无事,折腾了下,在最新的r3054版本基础上修改了一些东西,以备自己用,有兴趣的园友可以下载共同研究
1、添加了默认的授权规则
如果是列表对象则生成列表权限,User的只读列表和可编辑列表生成的都是User.List权限,admin角色具有所有权限:
public partial class UserInfoList { #region Authorization Rules /// <summary> /// Allows the specification of CSLA based authorization rules for a collection list. Specifies what roles can /// perform which operations for a given business object /// </summary> public static void AddObjectAuthorizationRules() { Csla.Rules.BusinessRules.AddRule(typeof(UserInfoList), new Csla.Rules.CommonRules.IsInRole(Csla.Rules.AuthorizationActions.GetObject, "admin","User.List")); } #endregion }
public partial class UserList { #region Authorization Rules /// <summary> /// Allows the specification of CSLA based authorization rules for a collection list. Specifies what roles can /// perform which operations for a given business object /// </summary> public static void AddObjectAuthorizationRules() { Csla.Rules.BusinessRules.AddRule(typeof(UserList), new Csla.Rules.CommonRules.IsInRole(Csla.Rules.AuthorizationActions.GetObject, "admin","User.List")); } #endregion }
如果是可编辑的跟对象则生成增删改读权限,admin角色具有所有权限:
public partial class User { #region Authorization Rules /// <summary> /// Allows the specification of CSLA based authorization rules. Specifies what roles can /// perform which operations for a given business object /// </summary> public static void AddObjectAuthorizationRules() { Csla.Rules.BusinessRules.AddRule(typeof(User), new Csla.Rules.CommonRules.IsInRole(Csla.Rules.AuthorizationActions.GetObject, "admin","User.Get")); Csla.Rules.BusinessRules.AddRule(typeof(User), new Csla.Rules.CommonRules.IsInRole(Csla.Rules.AuthorizationActions.CreateObject, "admin","User.Create")); Csla.Rules.BusinessRules.AddRule(typeof(User), new Csla.Rules.CommonRules.IsInRole(Csla.Rules.AuthorizationActions.EditObject, "admin","User.Edit")); Csla.Rules.BusinessRules.AddRule(typeof(User), new Csla.Rules.CommonRules.IsInRole(Csla.Rules.AuthorizationActions.DeleteObject, "admin", "User.Delete")); } #endregion }
2、生成权限列表的sql脚本
对应生成的权限脚本:
insert into S_Permision(Name) values('User.List'); insert into S_Permision(Name) values('User.Get'); insert into S_Permision(Name) values('User.Create'); insert into S_Permision(Name) values('User.Edit'); insert into S_Permision(Name) values('User.Delete');
3、添加了查询支持
criteria本来的查询是每个字段都是取相等的值,改造后,cirteria中每个对应的字段都增加了一个字段名+Operator的属性。Operator的值即可根据用户选择 like ,not like ,> , < ,<>
var form = ASPxNavBar1.Groups[0].FindControl("ASPxFormLayout1") as ASPxFormLayout; var criteria = new Business.UserCriteria(); Csla.Data.DataMapper.Map(FormHelper.GetFormData(form), criteria); return criteria;
public class FormHelper { public static Dictionary<string, object> GetFormData(DevExpress.Web.ASPxFormLayout.ASPxFormLayout form) { var dict = new Dictionary<string, object>(); foreach (DevExpress.Web.ASPxFormLayout.LayoutItem item in form.Items) { if (string.IsNullOrEmpty(item.FieldName)) continue; if (dict.ContainsKey(item.FieldName)) throw new Exception("布局中存在重复的字段"); var value = form.GetNestedControlValueByFieldName(item.FieldName); if (value != null) dict.Add(item.FieldName, value); } return dict; } }
4、添加了批量删除
没有加到模板中,直接复制即可使用,但是用到了criteria中新加的属性
[Serializable] public class MultyDeleteCommand<T, C> : CommandBase<MultyDeleteCommand<T, C>> where T : BusinessBase<T> where C : IGeneratedCriteria, new() { #region Authorization Methods public static bool CanExecuteCommand() { return Csla.Rules.BusinessRules.HasPermission(Csla.Rules.AuthorizationActions.DeleteObject, typeof(T)); } #endregion #region Factory Methods public static bool Execute(IEnumerable<object> pkList) { if (!CanExecuteCommand()) throw new System.Security.SecurityException("没有权限执行删除操作"); MultyDeleteCommand<T, C> cmd = new MultyDeleteCommand<T, C>(); cmd.PKList = pkList; cmd.BeforeServer(); cmd = DataPortal.Execute<MultyDeleteCommand<T, C>>(cmd); cmd.AfterServer(); return cmd.Result; } private MultyDeleteCommand() { /* require use of factory methods */ } #endregion #region Client-side Code public static readonly PropertyInfo<bool> ResultProperty = RegisterProperty<bool>(p => p.Result); public bool Result { get { return ReadProperty(ResultProperty); } set { LoadProperty(ResultProperty, value); } } public IEnumerable<object> PKList { get; set; } private void BeforeServer() { // TODO: implement code to run on client // before server is called } private void AfterServer() { // TODO: implement code to run on client // after server is called } #endregion #region Server-side Code protected override void DataPortal_Execute() { string temp = ""; string key = ""; var criteria = new C(); if (string.IsNullOrWhiteSpace(criteria.TableFullName) || string.IsNullOrWhiteSpace(criteria.PKName)) throw new Exception("表名和主键名不能为空"); SqlParameter[] parm = new SqlParameter[PKList.Count()]; //初始化参数个数 for (int i = 0; i < PKList.Count(); i++) { key = "@StringId" + i.ToString(); temp += key + ","; //将每个参数连接起来 parm[i] = new SqlParameter(key, PKList.ElementAt(i)); } temp = (temp + ")").Replace(",)", ""); //去掉最后一个逗号 string commandText = string.Format("DELETE {0} WHERE [{1}] IN ({2})",criteria.TableFullName, criteria.PKName, temp); if (!string.IsNullOrEmpty(criteria.SoftDeletedName)) commandText = string.Format("UPDATE {0} SET [{1}]=1 WHERE [{2}] IN ({3})", criteria.TableFullName, criteria.SoftDeletedName, criteria.PKName, temp); using (var connection = new SqlConnection(ADOHelper.ConnectionString)) { connection.Open(); using (var command = new SqlCommand(commandText, connection)) { command.Parameters.AddRange(parm); //result: The number of rows changed, inserted, or deleted. -1 for select statements; 0 if no rows were affected, or the statement failed. int result = command.ExecuteNonQuery(); if (result == 0) throw new DBConcurrencyException("您提交的数据已过期,请刷新您的界面后重试."); else Result = true; } } } #endregion }
5、添加了软删除的功能
当数据表中有一列名为bit类型的DeleteFlag(默认值为0,not null)时,自动启用软删除,即执行对象的删除操作时并不是从数据库中删除对象,而是设置DeleteFlag字段为1,使用criteria条件查询时,除非指定显式设置DeletedFlag属性值,否则默认按照DeleteFlag<>1查询,即已经删除的记录不会查出来,就像真的被从数据库中删除了一样。
如果要修改数据库中的列名,修改模板Common\AutoColunmConfig.cst中的DeletedFlag属性即可
6、添加了添加修改时间,创建者修改者的自动处理
数据库表中存在CreateAt,UpdateAt,CreateUserID,UpdateUserID时自动生成代码,在Common\AutoColunmConfig.cst模板中可以配置对应的数据库字段和读取当前用户ID的代码。UserIDAccessor配置生成当前用户ID的代码。
<%@ Property Name="DeletedFlag" Default="DeletedFlag" Type="System.String" %>
<%@ Property Name="Create_At" Default="CreateAt" Type="System.String" %>
<%@ Property Name="Update_At" Default="UpdateAt" Type="System.String" %>
<%@ Property Name="Create_UserID" Default="CreateUserID" Type="System.String" %>
<%@ Property Name="Update_UserID" Default="UpdateUserID" Type="System.String" %>
<%@ Property Name="UserIDAccessor" Default="Csla.ApplicationContext.User == null ? (int?)null : (Csla.ApplicationContext.User.Identity as MFKIdentity).UserID" Type="System.String" %>
7、添加了禁止删除系统预设字段的业务规则(不在模板中,复制代码在需要的地方调用即可)
1 public class DenyDeleteSystemDefinedObject<T> : Csla.Rules.CommonRules.IsInRole 2 where T : Csla.BusinessBase<T> 3 { 4 Func<T, bool> isSystemDefined; 5 public DenyDeleteSystemDefinedObject(Func<T, bool> _isSystemDefined, params string[] roles) 6 : base(Csla.Rules.AuthorizationActions.DeleteObject, roles) 7 { 8 isSystemDefined = _isSystemDefined; 9 } 10 11 protected override void Execute(Csla.Rules.AuthorizationContext context) 12 { 13 base.Execute(context); 14 if (!context.HasPermission) return; 15 16 if (context.Target != null && context.Target is T && isSystemDefined(context.Target as T)) 17 { 18 context.HasPermission = false; 19 throw new System.InvalidOperationException(Properties.Resources.SystemDefinedObjectCannotDelete); 20 } 21 } 22 }
使用方式,例如:有一个系统设置的根对象Setting:
1 public partial class Setting: BusinessBase<Setting> 2 { 3 static Dictionary<int, string> _systemDefinedList = null; 4 /// <summary> 5 /// 系统预设值 6 /// </summary> 7 public static Dictionary<int, string> SystemDefined 8 { 9 get 10 { 11 if (_systemDefinedList == null) 12 { 13 _systemDefinedList = new Dictionary<int, string>(); 14 _systemDefinedList.Add(1, "站点名称"); 15 _systemDefinedList.Add(2, "LOGO图片"); 16 } 17 return _systemDefinedList; 18 } 19 } 20 21 public bool IsSystemDefined 22 { 23 get 24 { 25 return Setting.SystemDefined.ContainsValue(KeyName) || Setting.SystemDefined.ContainsKey(Identification); 26 } 27 } 28 29 #region Authorization Rules 30 31 /// <summary> 32 /// Allows the specification of CSLA based authorization rules. Specifies what roles can 33 /// perform which operations for a given business object 34 /// </summary> 35 public static void AddObjectAuthorizationRules() 36 { 37 Csla.Rules.BusinessRules.AddRule(typeof(Setting), new Csla.Rules.CommonRules.IsInRole(Csla.Rules.AuthorizationActions.GetObject, "admin", "Setting.Get")); 38 Csla.Rules.BusinessRules.AddRule(typeof(Setting), new Csla.Rules.CommonRules.IsInRole(Csla.Rules.AuthorizationActions.CreateObject, "admin", "Setting.Create")); 39 Csla.Rules.BusinessRules.AddRule(typeof(Setting), new Csla.Rules.CommonRules.IsInRole(Csla.Rules.AuthorizationActions.EditObject, "admin", "Setting.Edit")); 40 Csla.Rules.BusinessRules.AddRule(typeof(Setting), new DenyDeleteSystemDefinedObject<Setting>( 41 s => s.IsSystemDefined, "admin", "Setting.Delete")); 42 } 43 #endregion 44 45 46 partial void OnDeleting(SettingCriteria criteria, ref bool cancel) 47 { 48 if (Setting.SystemDefined.ContainsValue(criteria.KeyName) 49 || Setting.SystemDefined.ContainsKey(criteria.Identification)) 50 { 51 throw new System.InvalidOperationException(Properties.Resources.SystemDefinedObjectCannotDelete); 52 } 53 } 54 }
注意事项:
1、表名不能以Info结尾
2、字段名不可以和Csla的业务对象的同名,例如: 字段名不能为Parent,IsDeleted 等