using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using Csla;
using Csla.Data;
namespace ProjectTracker.Library
{
[Serializable()]
public class Project : BusinessBase<Project>//源自业务基类,泛型提供强类型的Save及Clone
{
#region Business Methods 业务方法
private byte[] _timestamp = new byte[8];
private ProjectResources _resources = ProjectResources.NewProjectResources();//当前对象的子集合对象
/// <summary>
/// 主键,类的私有变量:采用加“m”前缀,例如mWorkerName;m+属性名--在本例中使用的是下划线首字母小写,这样会在复制代码和写"_"的时候代码麻烦
/// </summary>
private Guid _id;
[System.ComponentModel.DataObjectField(true, true)]//此特性是用来识别一下属性既是主键,又是可以唯一标识此对象的识别值(410)
public Guid Id//此属性只读
{
//制定方法如何实现,指定此方法不能内联,我想是提供给反射使用的一个特性。
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]//此特性并没有介绍但基类的属性都有所有默认添加
get
{
CanReadProperty(true);//此方法在当前用户无权读取这个属性的时候抛出SecurityException异常,你也可以通过此方法的返回值判断用户是否有权限(410)
return _id;
}
}
/// <summary>
/// 项目名字
/// </summary>
string _name = string.Empty;
public string Name//此属性可读写(411)
{
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
get
{
CanReadProperty(true);//是否有权限读取此属性
return _name;
}
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
set
{
CanWriteProperty(true);
if (value == null) value = string.Empty;//如果值是空,付给empty
if (!_name.Equals(value))//如果即将付的值与当前的值不同时,赋值才是有意义的
{
_name = value;//先赋值后验证的目的是,验证已经假设被验证的属性值在当前的属性中了
PropertyHasChanged();//1调用对数据验证规则的检查AddBusinessRules,2,IsDirty标记已经修改,3,出发属性更改事件提供给UI刷新的警示(411),发生变化就要调用此方法
}
}
}
/// <summary>
/// 起始时间
/// </summary>
SmartDate _started;
public string Started
{
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
get
{
CanReadProperty(true);
return _started.Text;
}
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
set
{
CanWriteProperty(true);
if (value == null) value = string.Empty;
if (!_started.Equals(value))
{
_started.Text = value;
ValidationRules.CheckRules("Ended");//手动的激活特定的,比如这个是Ended相关的验证规则
PropertyHasChanged();
}
}
}
/// <summary>
/// 结束时间
/// </summary>
SmartDate _ended = new SmartDate(false);
public string Ended
{
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
get
{
CanReadProperty(true);
return _ended.Text;
}
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
set
{
CanWriteProperty(true);
if (value == null) value = string.Empty;
if (!_ended.Equals(value))
{
_ended.Text = value;
PropertyHasChanged();
}
}
}
/// <summary>
/// 项目描述
/// </summary>
string _description = string.Empty;
public string Description
{
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
get
{
CanReadProperty(true);
return _description;
}
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
set
{
CanWriteProperty(true);
if (value == null) value = string.Empty;
if (!_description.Equals(value))
{
_description = value;
PropertyHasChanged();
}
}
}
public ProjectResources Resources //返回子对象集合的引用
{
get { return _resources; }
}
public override bool IsValid //因为此对象有子对象,所以扩充了IsValie检查是否有效,返回true代表有效,返回false代表无效
{
get { return base.IsValid && _resources.IsValid; }
}
public override bool IsDirty //由于有子对象,所以扩成此IsDirty方法,验证自身或者子对象是否有修改过
{
get { return base.IsDirty || _resources.IsDirty; }
}
protected override object GetIdValue()//提供Id,是为了支持Object的,Equals().toString(),GetHashCode()
{
return _id;
}
#endregion
#region Validation Rules 验证规则
//将验证规则与业务对象的属性联系在一起
protected override void AddBusinessRules()
{
//AddRule的第一个参数是委托变量,也就是说是方法的变量
ValidationRules.AddRule(Csla.Validation.CommonRules.StringRequired, "Name");
ValidationRules.AddRule(Csla.Validation.CommonRules.StringMaxLength, new Csla.Validation.CommonRules.MaxLengthRuleArgs("Name", 50));
ValidationRules.AddRule<Project>( StartDateGTEndDate<Project>, "Started");
ValidationRules.AddRule<Project>( StartDateGTEndDate<Project>, "Ended");
ValidationRules.AddDependantProperty("Started", "Ended", true);
//base.AddBusinessRules();
}
private static bool StartDateGTEndDate<T>( T target, Csla.Validation.RuleArgs e) where T : Project
{
if (target._started > target._ended)
{
e.Description = "开始日期不能晚于结束日期.";
return false;
}
else
return true;
}
#endregion
#region Authorization Rules 授权规则
//CSLA设置授权规则时候自动调用
//也许是在CanRead,和CanWrite方法时候被调用
protected override void AddAuthorizationRules()
{
//制定什么属性可以由什么权限读写
//对于没有给出read权限定义的属性代表所有人都可以对其进行访问
//第二个参数是一个参数数组所以你可以为某个属性指定多个角色
//也许是在CanRead,和CanWrite方法时候被调用
AuthorizationRules.AllowWrite( "Name", "ProjectManager");
AuthorizationRules.AllowWrite( "Started", "ProjectManager");
AuthorizationRules.AllowWrite( "Ended", "ProjectManager");
AuthorizationRules.AllowWrite( "Description", "ProjectManager");
}
//下面的四个方法用来为UI提供数据,告诉UI那些功能可以对当前用户隐藏
public static bool CanAddObject()
{
return Csla.ApplicationContext.User.IsInRole( "ProjectManager");//这个方法会判断当前用户是不是ProjectManager是返回True
}
public static bool CanGetObject()
{
return true;
}
public static bool CanDeleteObject()
{
bool result = false;
if (Csla.ApplicationContext.User.IsInRole( "ProjectManager"))
result = true;
if (Csla.ApplicationContext.User.IsInRole( "Administrator"))
result = true;
return result;
}
public static bool CanEditObject()
{
return Csla.ApplicationContext.User.IsInRole("ProjectManager");
}
#endregion
#region Factory Methods 工厂方法
public static Project NewProject()
{
//看,他调用,刚才定义的CanAddObject方法去判断当前用户是否在,可以创建一个对象的权限组中,如果没有执行破除一个异常
if (!CanAddObject())
throw new System.Security.SecurityException( "当前用户没有权限添加工程");
//调用数据门户,数据访问方法
return DataPortal.Create<Project>();
}
/// <summary>
/// 通过ID,获得一个对象
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public static Project GetProject(Guid id)
{
if (!CanGetObject())
throw new System.Security.SecurityException( "当前用户没有权限去查看工程");
return DataPortal.Fetch<Project>(new Criteria(id));
}
/// <summary>
/// 通过ID,删除一个对象
/// </summary>
/// <param name="id"></param>
public static void DeleteProject(Guid id)
{
if (!CanDeleteObject())
throw new System.Security.SecurityException( "当前用户没有权限删除工程");
DataPortal.Delete(new Criteria(id));
}
//私有的默认构造,强迫UI通过工厂方法创建对象
private Project()
{ /* require use of factory methods */ }
public override Project Save()
{
//如果已经标记为删除标记,那么会继续判断是否有删除权限
if (IsDeleted && !CanDeleteObject())
throw new System.Security.SecurityException("当前用户没有权限删除工程");
//是新的,会继续判断能否添加
else if (IsNew && !CanAddObject())
throw new System.Security.SecurityException("当前用户没有权限添加工程");
//是否可以编辑
else if (!CanEditObject())
throw new System.Security.SecurityException("当前用户没有权限更新工程");
//如果一切正常调用Save
return base.Save();
}
#endregion
#region Data Access 数据访问
[Serializable()]
private class Criteria
{
private Guid _id;
public Guid Id
{
get { return _id; }
}
public Criteria(Guid id)
{ _id = id; }
}
//由于DataPortal_create中没有对数据库的访问,所有标记了Runlocal特性,使得该方法只需在本地运行即可
//如果代码中有访问数据库的方法,那么就不要用这个特性,使数据门户可以根据情况将此方法的运行选择在应用服务器还是本地
[RunLocal()]
protected override void DataPortal_Create()
{
//非常值得注意的是主键是在这个时候被初始化的
_id = Guid.NewGuid();
_started.Date = DateTime.Today;
//(424)检查一下验证规则,对属性的设置也会引发此操作,然后上面是直接操作私有成员变量的,所以不会引发
//在此调用CheckRules对所有的属性进行验证规则的检查,这样检查只运行一次。
ValidationRules.CheckRules();
}
//可以看到此方法没有标记任何特性
//此方法要访问数据库所以不能标记本地,由于她没有任何数据库更新操作所以也无需事务性的保护
//此方法调用结束后会隐含的调用MarkOld()方法
private void DataPortal_Fetch(Criteria criteria)
{
//通过连接字符串建立SQL连接对象,Using符号代表,范围释放的意思,SqlConnection对象会在此范围后被释放掉
using (SqlConnection cn = new SqlConnection(Database.PTrackerConnection))
{
cn.Open();
//SQLCommand将在using后被释放
using (SqlCommand cm = cn.CreateCommand())
{
//存储过程
cm.CommandType = CommandType.StoredProcedure;
//存储过程名
cm.CommandText = "getProject";
//为存储过程添加参数
cm.Parameters.AddWithValue("@id", criteria.Id);
//SafeDatareader将在using后被释放,顺路说一下SafeDataReader是CSLA定义的集成DataReader的安全Reader
//提供对Null值的阻止和SmartDate数据类型的支持
//Using有两个作用, 保证对象的存在,以及在此范围内有效,过后就释放资源
using (SafeDataReader dr = new SafeDataReader(cm.ExecuteReader()))
{
dr.Read();
_id = dr.GetGuid("Id");
_name = dr.GetString("Name");
//GetSmartDate方法可以避免Null,以及将空置转换为何时的值
_started = dr.GetSmartDate("Started", _started.EmptyIsMin);
_ended = dr.GetSmartDate("Ended", _ended.EmptyIsMin);
_description = dr.GetString("Description");
//获取时间戳用于随后的更新操作
//1字段名,Fieldoffset,要装载的变量,bufferoffset,长度
dr.GetBytes("LastChanged", 0, _timestamp, 0, 8);
// 将dr定位到下一个结果集
dr.NextResult();
_resources = ProjectResources.GetProjectResources(dr);
}
}
}
}
//这是一个事务安全的,此种方法标记事务是非常简单且有效的
//数据门户会包裹这段代码,保证事务的完整运行成功,而且无需定义Ado的事务
[Transactional(TransactionalTypes.TransactionScope)]
protected override void DataPortal_Insert()
{
using (SqlConnection cn = new SqlConnection(Database.PTrackerConnection))
{
cn.Open();
using (SqlCommand cm = cn.CreateCommand())
{
cm.CommandText = "addProject";
//将cm做参数跳转到统一处理方法
DoInsertUpdate(cm);
}
}
// update child objects
_resources.Update(this);
}
[Transactional(TransactionalTypes.TransactionScope)]
protected override void DataPortal_Update()
{
//如果是修改过的才有意义去更新此对象
if (base.IsDirty)
{
using (SqlConnection cn = new SqlConnection(Database.PTrackerConnection))
{
cn.Open();
using (SqlCommand cm = cn.CreateCommand())
{
cm.CommandText = "updateProject";
cm.Parameters.AddWithValue("@lastChanged", _timestamp);
//将cm做参数跳转到统一处理方法
DoInsertUpdate(cm);
}
}
}
// update child objects
_resources.Update(this);
}
private void DoInsertUpdate(SqlCommand cm)
{
//存储过程
cm.CommandType = CommandType.StoredProcedure;
//参数
cm.Parameters.AddWithValue("@id", _id);
cm.Parameters.AddWithValue("@name", _name);
cm.Parameters.AddWithValue("@started", _started.DBValue);
cm.Parameters.AddWithValue("@ended", _ended.DBValue);
cm.Parameters.AddWithValue("@description", _description);
//一下要特殊介绍,此位置是定义一个从数据库存储过程中返回的参数,她的数据库类型是Timestamp,描述为Output输出的
//此属性的意思是“时间戳”,代表一条记录的不同时间下的版本,用版本的这个词很合适
SqlParameter param = new SqlParameter("@newLastChanged", SqlDbType.Timestamp);
param.Direction = ParameterDirection.Output;
cm.Parameters.Add(param);
//执行语句无需返回值
cm.ExecuteNonQuery();
//执行后返回的值
_timestamp = (byte[])cm.Parameters["@newLastChanged"].Value;
}
[Transactional(TransactionalTypes.TransactionScope)]
protected override void DataPortal_DeleteSelf()
{
//依然是调用下面的方法删除的,只是他此时可以获得自己的Id
DataPortal_Delete(new Criteria(_id));
}
[Transactional(TransactionalTypes.TransactionScope)]
private void DataPortal_Delete(Criteria criteria)
{
using (SqlConnection cn = new SqlConnection(Database.PTrackerConnection))
{
cn.Open();
using (SqlCommand cm = cn.CreateCommand())
{
cm.CommandType = CommandType.StoredProcedure;
cm.CommandText = "deleteProject";
cm.Parameters.AddWithValue("@id", criteria.Id);
cm.ExecuteNonQuery();
}
}
}
#endregion
#region Exists
/// <summary>
/// 静态方法,业务对象可以直接调用
/// </summary>
/// <param name="id">要查找的业务对象id</param>
/// <returns></returns>
public static bool Exists(Guid id)
{
//本地声明对象
ExistsCommand result;
//结果返回给本地,DataPortal通过数据门户调用服务器端方法在服务器执行,(NewExistscommand在本地创建),
//提供类型的泛型参数用于初始化基类,参数用来执行
result = DataPortal.Execute<ExistsCommand>(new ExistsCommand(id));
return result.Exists;//将执行对象的属性结果返回
}
/// <summary>
/// 私有的,用于提供给上面的静态方法使用的(456)
/// </summary>
[Serializable()]
private class ExistsCommand : CommandBase
{
private Guid _id;//执行需要存储的id,这样对移动对象是非常有用的
private bool _exists;//执行的结果,同样是移动对象的概念,将结果从应用服务器带回客户端
//公共属性
public bool Exists
{
get { return _exists; }
}
//构造函数
public ExistsCommand(Guid id)
{
_id = id;
}
protected override void DataPortal_Execute()
{
using (SqlConnection cn = new SqlConnection(Database.PTrackerConnection))
{
cn.Open();
using (SqlCommand cm = cn.CreateCommand())
{
cm.CommandType = CommandType.StoredProcedure;
cm.CommandText = "existsProject";
cm.Parameters.AddWithValue("@id", _id);
int count = (int)cm.ExecuteScalar();//执行返回的数量
_exists = (count > 0); //这句语句很简化哦
}
}
}
}
#endregion
}
}
代码下载:CSLA3.0中文学习演示程序1.2.rar
分享到:
相关推荐
8. **项目跟踪器实例**:在提供的"ProjectTracker"示例中,开发者可以看到如何将这些概念应用到实际项目中。这个例子展示了如何创建一个简单的项目管理应用,包括任务分配、时间追踪等功能,是学习CSLA.NET的绝佳...
5. **事务处理**:CSLA.NET支持事务管理,可以轻松地在业务逻辑中包裹多个数据库操作,确保数据操作的原子性。 6. **单元测试**:框架设计考虑了测试驱动开发,使得编写和运行单元测试变得简单,从而提高软件质量。...
1. **框架目标**:Csla.Net的主要目标是简化业务层的开发,通过提供一系列预定义的基类和工具,帮助开发者快速构建符合企业级标准的业务对象。 2. **设计原则**:遵循SOLID原则,包括单一职责原则、开闭原则、里氏...
5. **安全性与权限管理**:CSLA.NET提供了内置的安全性和权限管理机制,可以控制用户对业务对象的访问权限。这部分内容会涵盖如何设置和实施这些安全策略。 6. **单元测试与持续集成**:作为企业级应用,单元测试和...
CSLA.NET 4.0 源码是一个用于构建企业级业务对象的框架,它源自Chuck Noble所著的《Expert C# Business Objects》一书。这个框架的核心目标是提供一个可扩展、易于维护的解决方案,帮助开发人员创建复杂的业务逻辑层...
C#企业应用开发艺术CSLA.NET框架开发实战.part1.rar(PDF加源码)
[CSLA.NET] Using CSLA 4 eBook Series ☆ 图书概要:☆ The Using CSLA 4 ebook series will teach you how to use CSLA 4 to create powerful object-oriented business layers for your applications, as well ...
CSLA (Component Services Library for Applications) .NET框架是由Rockford Lhotka创建的,它为.NET平台提供了一种强大的业务对象开发模型。该框架的主要目标是帮助开发人员构建可复用、可维护和灵活的业务应用程序...
CSLA .NET的核心是它的业务对象模型,该模型允许开发者定义强类型、可验证且具有状态管理能力的对象。通过使用 CSLA,开发者可以将业务逻辑与数据访问层分离,从而提高代码的可重用性和可测试性。例如,你可以创建可...
CSLA.NET 框架成为了微软.NET 平台上最广泛应用的开发框架之一,本书介绍了CSLA.NET 3.6 架构背后的构思过程,描述了怎样搭建支持这个架构的框架,如何创建应用程序的业务对象,并且展示了如何使用这个框架创建基于...
《#企业应用开发艺术CSLA.NET框架开发实战》(Expert C#2008 Business Objects)配套源码及例程csla-4.5.700。 CSLA .NET is a software development framework that helps you build a reusable, maintainable ...
[Apress] CSLA .NET 框架企业应用开发艺术 (2008 版本) (英文版) [Apress] Expert C# 2008 Business Objects (E-Book) ☆ 图书概要:☆ In Rockford Lhotka’s Expert C# 2008 Business Objects, you’ll learn ...
Csla的核心理念是提供一套可复用的、基于组件的业务对象模型,这些对象可以在客户端和服务器端之间无缝地工作,支持数据验证、安全性、状态管理等功能。框架的灵活性使得开发人员能够专注于业务逻辑,而不是重复的...
5. **更完善的文档和示例**:随着版本的更新,CSLA.NET的文档通常会得到更新,提供更详尽的教程和示例,帮助开发者快速上手。 **压缩包内容分析** "README.txt" 文件很可能是包含了安装指南、更新内容和注意事项的...
Visual Studio CSLA Extension for ADO.NET Entity Framework. Visual Studio extension and T4 templates for generation of CSLA objects from ADO.NET Entity Framework model. CSLA.NET框架面向实体框架的代码...
Framework,Nhibernate等都能够支持.CSLA.NET还支持在业务对象上构建WPF、ASP.NET(Web Forms、AJAX和 MVC)和Windows Forms,WCF service,Windows Workflow,web Services,Silverlight等用户接口. CSLA.NET开始于...
8. **项目Tracker cs**:在压缩包中的"ProjectTracker cs"可能是一个使用CSLA .NET 框架开发的示例项目,它演示了如何将CSLA的特性应用于实际的项目管理应用中,包括任务跟踪、资源分配等功能。 综上所述,CSLA ...
### 使用CSLA 4:CSLA .NET概览 #### 一、CSLA .NET简介 **CSLA(Component-based Scalable Logical Architecture)**是一种面向对象的应用程序开发框架,主要针对.NET平台。它由Rockford Lhotka创建,并在多个...
这本书籍通过深入浅出的方式,为读者揭示了如何高效地利用CSLA.NET来构建可复用、可维护的业务对象,是C#开发者学习企业级应用开发的重要资源。 CSLA.NET是由Rockford Lhotka创建的一个开源框架,它为.NET平台提供...
2. **数据访问**:Csla.NET 提供了多种数据访问策略,包括ADO.NET、Entity Framework、NHibernate等,可以根据项目需求选择合适的方式。 3. **验证(Validation)**:Csla.NET 提供了一套完整的验证规则框架,允许...