博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
信息系统开发平台OpenExpressApp - 支持差异保存
阅读量:6503 次
发布时间:2019-06-24

本文共 3564 字,大约阅读时间需要 11 分钟。

  在《》中提到:

CSLA目前通用做法是整个对象在网络上传输,客户端更新时不管是更新了多少内容,它会把整个对象返回到服务器端。如果这个对象有成百上千条记录,而只更新了一两条记录,那么回传整个对象无疑是一个很大的浪费。在业务逻辑不需要整个对象的情况下,我们可以做差异更新,只回传增加、更新或删除的数据到服务器端。

  现在支持差异更新保存命令,单据类对象的保存默认都是按照差异更新来处理。下面简单介绍一下如何结合OpenExpressApp来修改CSLA框架实现此功能。

如何调用

       CSLA自带一个差异更新的示例Csla.DiffGram,但是它的例子需要每个类库再继承写一个支持获取差异数据和保存以及回传的类,这对框架来说无疑是很不合适的,我不希望差异保存功能这样侵蚀以前写的类,也不想再去重新实现匹配的类,所以我想是否能够按照一种统一的方式,由外部调用来完成此功能,最好直接调用一个Command解决,如下代码所示:

[Command(CommandNames.Save_Bill, Label = "保存", ToolbarType = ToolbarType.Main, ModuleType = ModuleType.Bill, ToolTip = "保存记录")]

public class SaveBillCommand : WPFViewCommand
{
    public override void Execute(ObjectView view)
    {
        DiffSaveCommand.Execute(view.CurrentObject as BusinessBase);
    }
}

DiffSaveCommand实现

      如果通过DiffSaveCommand实现差异更新,那么必须把差异的内容作为一个对象传送回服务器端,而又不想重新写类,最好重用以前类的保存逻辑,现在是把保存的对象clone一个出来,然后删除这个对象中未更改的子对象,这样传送回服务器端的既是一个只保留更新记录的原始对象类,也自然可以调用原始对象的Save方法了。

[Serializable]

public class DiffSaveCommand: CommandBase
{
    public static void Execute(BusinessBase businessBase)
    {
        DiffSaveCommand cmd = new DiffSaveCommand(businessBase);
        cmd = DataPortal.Execute<DiffSaveCommand>(cmd);

        MakeOldRecurChildObject(businessBase);  //记住:调用成功后,把原始对象状态设置为Old

    }

    //设置原始对象状态

    private static void MakeOldRecurChildObject(BusinessBase businessBase)
    {
        businessBase.MarkOld();
        BusinessObjectInfo boInfo = ApplicationModel.GetBusinessObjectInfo(businessBase.GetType());

        foreach (var item in boInfo.BOsPropertyInfos)

        {
            //如果是懒加载属性,并且没有加载数据时,不需要遍历此属性值
            if (!businessBase.FieldExists(item.Name)) continue;
            IList childs = businessBase.GetPropertyValue(item.Name) as IList;
            ((childs as IEditableCollection).GetDeletedList() as IList).Clear();
            for (int i = childs.Count - 1; i >= 0; i--)
            {
                BusinessBase child = childs[i] as BusinessBase;
                if (child.IsDirty) MakeOldRecurChildObject(child);
            }
        }
    }

    private BusinessBase diffBo;

    private DiffSaveCommand(BusinessBase businessBase)
    {
        diffBo = (businessBase as ICloneable).Clone() as BusinessBase;
        //抱着传送对象只包含更新过的对象
        DeleteNotDirtyData(diffBo);
    }

    protected override void DataPortal_Execute()

    {
        (diffBo as ISavable).Save();
    }

    //删除没有更改的子对象

    private void DeleteNotDirtyData(BusinessBase businessBase)
    {
        BusinessObjectInfo boInfo = ApplicationModel.GetBusinessObjectInfo(businessBase.GetType());

        //删除没有变化的子对象

        foreach (var item in boInfo.BOsPropertyInfos)
        {
            //如果是懒加载属性,并且没有加载数据时,不需要遍历此属性值
            if (!businessBase.FieldExists(item.Name)) continue;
            IList childs = businessBase.GetPropertyValue(item.Name) as IList;
            for (int i = childs.Count - 1; i >= 0; i--)
            {
                BusinessBase child = childs[i] as BusinessBase;
                if (!child.IsDirty)
                {
                    (childs as IEditableCollection).RemoveChild(child);
                    ((childs as IEditableCollection).GetDeletedList() as IList).Remove(child);
                }
                else
                    DeleteNotDirtyData(child as BusinessBase);
            }

        }

    }
}

更改CSLA

        从上面Command实现可以看出,我给BusinessBase类添加了一个FieldExists方法,这个方法用来判断懒加载属性是否已经加载了对象,如果没有加载的话,上面Command删除非更新子对象时就不用去遍历这个懒加载属性了,否则会触发一次客户端到服务器的请求。

/// 是否存在属性值,懒加载还没加载时不存在

public bool FieldExists(string propertyName)
{
    PropertyInfoList list = PropertyInfoManager.GetRegisteredProperties(this.GetType());
    foreach(var item in list)
    {
        if (item.Name == propertyName)
            return FieldManager.FieldExists(item);
    }
    return false;
}

CSLA保存后不回传对象

   在《》也提到,CSLA目前对象保存时会从服务器端传回一个对象,如果更新后回传的对象和本地的完全一样,则我们可以不必要回传这个对象。现在通过以上差异更新时,回传回来的只是差异更新的对象,而对于不需要回传保存后数据库信息的仍旧可以使用以前保存的那个对象,所以只需要在Command保存后对原始对象设置Old状态即可,这样也不需要重新刷新对象了,保存后界面也保持保存前一致。

    public static void Execute(BusinessBase businessBase)

    {
        DiffSaveCommand cmd = new DiffSaveCommand(businessBase);
        cmd = DataPortal.Execute<DiffSaveCommand>(cmd);

        MakeOldRecurChildObject(businessBase);  //记住:调用成功后,把原始对象状态设置为Old

    }

 

转载地址:http://damyo.baihongyu.com/

你可能感兴趣的文章
九州云实战人员为您揭秘成功部署OpenStack几大要点
查看>>
1.电子商务支付方式有哪些 2.比较不同支付方式的优势劣势
查看>>
医疗卫生系统被爆漏洞,7亿公民信息泄露……
查看>>
神秘函件引发的4G+与全网通的较量
查看>>
CloudCC:智能CRM究竟能否成为下一个行业风口?
查看>>
高德开放平台推出LBS游戏行业解决方案提供专业地图平台能力支持
查看>>
追求绿色数据中心
查看>>
Web开发初学指南
查看>>
OpenStack Days China:华云数据CTO郑军分享OpenStack创新实践
查看>>
探寻光存储没落的真正原因
查看>>
高通64位ARMv8系列服务器芯片商标命名:Centriq
查看>>
中国人工智能学会通讯——融合经济学原理的个性化推荐 1.1 互联网经济系统的基本问题...
查看>>
盘点大数据商业智能的十大戒律
查看>>
戴尔为保护数据安全 推出新款服务器PowerEdge T30
查看>>
今年以来硅晶圆涨幅约达40%
查看>>
构建智能的新一代网络——专访Mellanox市场部副总裁 Gilad Shainer
查看>>
《数字视频和高清:算法和接口》一导读
查看>>
《中国人工智能学会通讯》——6.6 实体消歧技术研究
查看>>
如何在Windows查看端口占用情况及查杀进程
查看>>
云存储应用Upthere获7700万美元股权债务融资
查看>>