【问题标题】:Fundamental principle about data management in FlexFlex中数据管理的基本原理
【发布时间】:2011-07-29 20:02:06
【问题描述】:

我不确定我的标题是否真的反映了这里发生的事情......我刚刚意识到,显然我在 Flex 处理数据(内存?)的方式中缺少一个基本原则,我需要一些帮助来明白了。

我有一个名为 friends 的 MySQL 表,其中包含以下行;

MySQL table friends
+-----------+----------+
| firstname | lastname |
+-----------+----------+
| Mark      | Smith    |
| Andrew    | Barnes   |
+-----------+----------+

在下一个示例中,我调用了我的 friendsService.getAllFriends() 三次,然后,我将结果分配给三个不同 DataGrid 的 DataProvider。

第二次向数据库发送查询时,我将 Mark 的名字更改为 Peter,只是在将结果分配给 DataProvider 之前。我不会以任何方式更新数据库,对吧? :-)

我的期望:

MyDataGrid1
+-----------+----------+
| firstname | lastname |
+-----------+----------+
| Mark      | Smith    |
| Andrew    | Barnes   |
+-----------+----------+

MyDataGrid2
+-----------+----------+
| firstname | lastname |
+-----------+----------+
| Peter     | Smith    | <---- Say hello to Peter :-)
| Andrew    | Barnes   |
+-----------+----------+

MyDataGrid3
+-----------+----------+
| firstname | lastname |
+-----------+----------+
| Mark      | Smith    |
| Andrew    | Barnes   |
+-----------+----------+

在调用第二个查询(我以编程方式将 Mark 切换为 Peter 的查询)之后,看起来 所有三个结果都以某种我不理解的方式绑定...我得到:

MyDataGrid1
+-----------+----------+
| firstname | lastname |
+-----------+----------+
| Peter     | Smith    |
| Andrew    | Barnes   |
+-----------+----------+

MyDataGrid2
+-----------+----------+
| firstname | lastname |
+-----------+----------+
| Peter     | Smith    |
| Andrew    | Barnes   |
+-----------+----------+

MyDataGrid3
+-----------+----------+
| firstname | lastname |
+-----------+----------+
| Peter     | Smith    |
| Andrew    | Barnes   |
+-----------+----------+

看起来 Flex 并没有真正要求新数据,假设它已经从 friendsService.getAllFriends() 得到答案...

对我有什么启示? :-)

谢谢!

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:friendsservice="services.friendsservice.*"
    creationComplete="creationCompleteHandler(event)">

    <fx:Script>
        <![CDATA[
            import mx.controls.Alert;
            import mx.events.FlexEvent;
            import mx.rpc.events.ResultEvent;

            private var _step:Number = 1;

            protected function creationCompleteHandler(event:FlexEvent):void
            {
                getAllFriends();
            }

            protected function getAllFriends():void
            {
                getAllFriendsResult.token = friendsService.getAllFriends();
            }

            protected function getAllFriendsResult_resultHandler(event:ResultEvent):void
            {

                if (_step == 1) {
                    assignValuesToDataGrid(MyDataGrid1, event.result, _step);
                    dbg.text = "MyDataGrid1 has been loaded";
                }

                if (_step == 2) {
                    assignValuesToDataGrid(MyDataGrid2, event.result, _step);
                    dbg.text = "MyDataGrid2 has been loaded";
                }

                if (_step == 3) {
                    assignValuesToDataGrid(MyDataGrid3, event.result, _step);
                    dbg.text = "MyDataGrid3 has been loaded";
                }

                _step++;
            }

            protected function assignValuesToDataGrid(dg:DataGrid, result:Object, step:Number):void
            {
                if (step == 2)
                    result[0].firstname = "Peter";

                dg.dataProvider = result;
            }

        ]]>
    </fx:Script>

    <fx:Declarations>
        <s:CallResponder id="getAllFriendsResult" result="getAllFriendsResult_resultHandler(event)"/>
        <friendsservice:FriendsService id="friendsService"/>
    </fx:Declarations>

    <s:layout>
        <s:VerticalLayout/>
    </s:layout>

    <s:Button label="Load next DataGrid" click="getAllFriends()"/>

    <mx:DataGrid id="MyDataGrid1" width="100%" height="100">
        <mx:columns>
            <mx:DataGridColumn headerText="First name" dataField="firstname"/>
            <mx:DataGridColumn headerText="Last name" dataField="lastname"/>
        </mx:columns>
    </mx:DataGrid>

    <mx:DataGrid id="MyDataGrid2" width="100%" height="100">
        <mx:columns>
            <mx:DataGridColumn headerText="First name" dataField="firstname"/>
            <mx:DataGridColumn headerText="Last name" dataField="lastname"/>
        </mx:columns>
    </mx:DataGrid>

    <mx:DataGrid id="MyDataGrid3" width="100%" height="100">
        <mx:columns>
            <mx:DataGridColumn headerText="First name" dataField="firstname"/>
            <mx:DataGridColumn headerText="Last name" dataField="lastname"/>
        </mx:columns>
    </mx:DataGrid>

    <s:Label id="dbg" fontWeight="bold"/>

</s:WindowedApplication>

【问题讨论】:

  • 我不熟悉您的 FriendService。假设这是一个自定义组件,看到它会有所帮助,或者至少是它的相关部分。
  • @Sam DeHaan My FriendService 只是使用 Flash Builder 4 中的“连接到数据/服务”工具生成的服务,使用数据类型 valueObject
  • 能否对函数 assignValuesToDataGrid 上的 _step 变量进行调试,以检查它被触发 3 次时的值是多少?
  • @Jivago,包括好友服务类。我认为可能涉及某种缓存。
  • @Angelo _step 变量在我每次调用函数时都会简单地递增,使用简单的 ++ 递增。这里不需要调试,我只是想要一个非常简单的方法来说明这里的问题。

标签: apache-flex data-binding air


【解决方案1】:

FriendService 使用 AbstractEntityMetadata 来管理实体。所以,我认为它是根据它的 ID 合并朋友。

我的意思是,假设 Mark 的 id 为 1,因为它是一个托管实体,当您对服务器进行新调用时,它不会创建新对象,而是首先搜索匹配 id 1 的实例并更新它。这就是所有三个数据网格都具有相同对象的原因。

【讨论】:

  • 问题与数据管理有关,请看我的回答,非常有趣。谢谢你,在某个地方你逼我花两天时间来调查这个问题:-)
  • 好的,那你为什么不接受我的回答呢?您的答案只是一个具体的答案,我已经回答问题是启用了数据管理。无论如何,很高兴你解决了你的问题。
【解决方案2】:

经过多次测试,我想我找到了问题所在。

当您使用 Connect to Data/Service 工具生成服务时,当使用选项 Generate sample 时,Flash Builder 会自动启用 Data Management 选项。

让我们看看文件 /src/services/friendservice/_Super_FriendService.as,我们有这个:

var dmOperation : mx.data.ManagedOperation;
var dmQuery : mx.data.ManagedQuery;

dmQuery = new mx.data.ManagedQuery("getAllFriends");
dmQuery.propertySpecifier = "id,firstname,lastname";
dmQuery.parameters = "";
_friendsRPCDataManager.addManagedOperation(dmQuery);

dmOperation = new mx.data.ManagedOperation("deleteFriends", "delete");
dmOperation.parameters = "id";
_friendsRPCDataManager.addManagedOperation(dmOperation);     

dmOperation = new mx.data.ManagedOperation("getFriendsByID", "get");
dmOperation.parameters = "id";
_friendsRPCDataManager.addManagedOperation(dmOperation);     

dmOperation = new mx.data.ManagedOperation("updateFriends", "update");
dmOperation.parameters = "item";
_friendsRPCDataManager.addManagedOperation(dmOperation);     

dmOperation = new mx.data.ManagedOperation("createFriends", "create");
dmOperation.parameters = "item";
_friendsRPCDataManager.addManagedOperation(dmOperation);

现在,让我们将 Connect to Data/Service 工具生成的 ValueObject 替换为自定义对象。

通过选择选项从示例数据中自动检测返回类型,Flash Builder 正在查询数据库、收集字段类型并相应地配置值对象。现在让我们再看看我们的_Super_FriendService.as:

var dmOperation : mx.data.ManagedOperation;
var dmQuery : mx.data.ManagedQuery;

dmOperation = new mx.data.ManagedOperation("deleteFriends", "delete");
dmOperation.parameters = "id";
_friendsRPCDataManager.addManagedOperation(dmOperation);     

dmOperation = new mx.data.ManagedOperation("getFriendsByID", "get");
dmOperation.parameters = "id";
_friendsRPCDataManager.addManagedOperation(dmOperation);     

dmOperation = new mx.data.ManagedOperation("updateFriends", "update");
dmOperation.parameters = "item";
_friendsRPCDataManager.addManagedOperation(dmOperation);     

dmOperation = new mx.data.ManagedOperation("createFriends", "create");
dmOperation.parameters = "item";
_friendsRPCDataManager.addManagedOperation(dmOperation);

惊喜,dmQuery = new mx.data.ManagedQuery("getAllFriends"); 块已经不存在了......我们知道我们可以禁用以下操作的数据管理(创建(添加)项目、获取项目、更新项目和删除项目强>)。

因此,通过使用自定义 ValueObject,我们获得了与生成的 ValueObject 完全相同的信息,而现在没有困扰我 2 天的块。我很高兴我找到了一个真正彻底禁用数据管理的解决方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-21
    • 2010-10-17
    • 2011-03-11
    • 1970-01-01
    相关资源
    最近更新 更多