开发者

Fundamental principle about data management in Flex

I'm not event sure if my title really reflect what's going on here... I just realized that apparently I'm missing a fundamental principle in the way Flex is handling data (memory?) and I need some help to understand it.

I have the a MySQL table named friends that contains the following rows ;

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

In the next example, I'm calling my friendsService.getAllFriends() three times and then, I assign the result to the DataProvider of three different DataGrids.

The second time I send a query to the database, I'm changing the firstname of Mark to Peter, only before assigning the result to the DataProvider. I'm not updating the database in any way, right? :-)

What I expect :

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

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

MyDataGrid3
+-----------+----------+
| firstname | lastname开发者_Python百科 |
+-----------+----------+
| Mark      | Smith    |
| Andrew    | Barnes   |
+-----------+----------+

After calling the second query (The one where I switch Mark to Peter programmatically), It looks like all three results are binded in some way I don't understand... I obtain :

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

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

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

It looks like Flex is not really asking for new data, assuming that it already have the answer from friendsService.getAllFriends() ...

Any enlightment for me? :-)

THANKS !

<?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>


The FriendService is using AbstractEntityMetadata to manage the entities. So, I think it is merging the friends based on it's IDs.

I mean, let's say Mark has id 1, since it is a managed entity, when you make a new call to the server, instead of creating new objects, it searches first for instances of matching id 1 and update it. That's why all three datagrids have the same objects.


After multiple tests, I think I found what's going on.

When you generate a service using the Connect to Data/Service tool, when using the option Generate sample, Flash Builder automatically enables the Data Managemement option.

Let's have a look at the file /src/services/friendservice/_Super_FriendService.as, somewhere we have this :

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);

Now, let's replace the ValueObject generated by the Connect to Data/Service tool with a custom object.

By choosing the option Auto-Detect the return type from sample data, Flash Builder is querying the database, gathering field types and configuring the value object accordingly. Now let's have a look at our _Super_FriendService.as again :

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);

Surprise, the dmQuery = new mx.data.ManagedQuery("getAllFriends"); block is not there anymore... And we know we can disable the Data Management for the following operations (Create (Add) Item, Get Item, Update Item and Delete Item).

So by using a custom ValueObject, we have exactly the same info as the generated ValueObject, without the block that bugged me for 2 days now. I'm just happy I figured out a workaround to really and completely disable Data Management.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜