CSLA.NET快速入门系列——实现子对象在WcfPorxy模式下的懒加载(LazyLoad)
在一般的业务系统中,父子关系的存在是非常广泛的,如订单和订单明细,部门和职员等。在前面的文章我们介绍了业务对象,命令对象和DataPortal的相关内容。
在CSLA框架中,父子关系是一个很重要的关系,相应的实体对应到业务对象和业务对象集合,并通过父对象的属性成员来使用子对象集合。
在一般应用中,有时只需要对root对象进行操作,而无需对其子对象进行操作,如果在加载root对象时,同时也将其所有子对象加载的话会造成比较差的性能。因此,CSLA框架提出了懒加载(LazyLoad)的概念,即只在需要操作子对象是才加载子对象。
在CSLA框架中,只有Root业务对象才允许直接访问数据源(服务端代码,后端)。因此,所有子对象的对数据源的访问必须通过其Root对象来进行,这样设计有利有弊,好处是开发人员直接利用OO的方式对对象进行操作,只需要一次调用Root对象即可对Root对象及其所有的子对象进行更新;不好的地方是无法直接对子对象数据源操作,同时,由于必须依赖于root对象对数据进行访问,即其无法单独“移动”(见前面DataPortal介绍)。
因此,当在使用WcfProxy模式下使用懒加载时,由于Root对象已经在客户端(前端),那么在加载子对象时,DataPortal运行时也在客户端,在加载时会出现空引用的问题(如数据源的连接),导致程序异常。
知道异常的原因,那么寻找解决方案就比较简单了,只要我们在加载子对象时,让DataPortal运行在后端,那么问题就迎刃而解。而在前面的文章中,我们介绍了命令对象,命令对象刚好已经在服务端执行的命令。因此,要以利用命令对象来解决LazyLoad时的问题。
当然,我们不需要为不同的子对象加载分别创建命令对象,而是可以通过实现一个通用命令对象来完成子对象加载的操作。
创建子对象加载命令对象LazyLoadChildCommand,如下:
 View Code
View Code [Csla.Server.ObjectFactory(FactoryNames.LazyLoadChildCommandFactoryName)]
public class LazyLoadChildCommand : CommandBase<LazyLoadChildCommand>
{
private const BindingFlags factoryFlags = BindingFlags.Static|
BindingFlags.NonPublic | BindingFlags.Public |
BindingFlags.FlattenHierarchy;
#region Authorization Methods
public static bool CanExecuteCommand()
{
return true;
}
#endregion
#region Client-side Code
internal string MethodName
{
get;set;
}
internal Type TargetObjectType
{
get;
set;
}
internal object[] Parameters { get; set; }
public Object Result { get; internal set; }
private void BeforeServer(string factoryMethodName, Type targetType, params object[] parameters)
{
MethodName = factoryMethodName;
this.Parameters = parameters;
this.TargetObjectType = targetType;
Result = null;
}
private void AfterServer()
{
}
#endregion
public static T Execute<T>(string factoryMethodName, params object[] Parameters) where T : class
{
if (!CanExecuteCommand())
throw new System.Security.SecurityException("Not authorized to execute command");
var cmd = new LazyLoadChildCommand();
cmd.BeforeServer(factoryMethodName,typeof(T), Parameters);
cmd = DataPortal.Execute(cmd);
cmd.AfterServer();
return (T)cmd.Result;
}
public static object CallFactoryMethod(Type objectType, string method, params object[] Parameters)
{
object returnValue;
System.Reflection.MethodInfo factory = objectType.GetMethod(
method, factoryFlags, null,
MethodCaller.GetParameterTypes(Parameters), null);
if (factory == null)
{
int parameterCount = Parameters.Length;
System.Reflection.MethodInfo[] methods = objectType.GetMethods(factoryFlags);
foreach (System.Reflection.MethodInfo oneMethod in methods)
if (oneMethod.Name == method && oneMethod.GetParameters().Length == parameterCount)
{
factory = oneMethod;
break;
}
}
if (factory == null)
{
throw new InvalidOperationException(
string.Format(Resources.NoSuchFactoryMethod, method));
}
try
{
returnValue = factory.Invoke(null, Parameters);
}
catch (Exception ex)
{
Exception inner = null;
if (ex.InnerException == null)
inner = ex;
else
inner = ex.InnerException;
throw new CallMethodException(factory.Name + " " + Resources.MethodCallFailed, inner);
}
return returnValue;
}
}
静态工厂方法public static T Execute<T>(string factoryMethodName, params object[] Parameters)
T:为要获取的子业务对象集合
factoryMethodName:为子业务对象集合类业务方法(根据父对象唯一键获取子对象集合的方法,为静态工厂方法)
Parameters:为factoryMethodName业务方法的参数。
最后我们再在父对象的相应子象集合属性get处理:
public ScrumProjectReleaseList ScrumProjectReleases
{
get
{
bool cancel = false;
OnChildLoading(_scrumProjectReleasesProperty, ref cancel);
if (!cancel)
{
if(!FieldManager.FieldExists(_scrumProjectReleasesProperty))
{
var criteria = new ScrumRM.Business.ScrumProjectReleaseCriteria {ProjectId = Identification};
if(!ScrumRM.Business.ScrumProjectReleaseList.Exists(criteria))
LoadProperty(_scrumProjectReleasesProperty, ScrumRM.Business.ScrumProjectReleaseList.NewList());
else LoadProperty(_scrumProjectReleasesProperty, LazyLoadChildCommand.Execute<ScrumProjectReleaseList>("GetByProjectId", Identification));
}
}
return GetProperty(_scrumProjectReleasesProperty);
}
}
这样,我们就实现了子对象在WcfPorxy模式下的懒加载(LazyLoad)的一种方案。
 
                    
                     
                    
                 
                    
                 
 
        
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号