JsonReader的idProperty属性有关问题

 

分类: Ext3.0

      JsonReader有一个idProperty,是用来标识record,如果不指定idProperty的话,会自动创建一个‘id’字段

      JsonReader从服务器读过来的数据储存在store,record有两个操作比较类似:修改和创建。如果该记录存在于服务器的话,那就应该是更新操作,否则则为插入。store用record的phantom属性值判断action,phantom值为TRUE的话action就是create了,看下面的源代码可以发现在从服务器load的时候,就先把phantom设置为FALSE了,当给record赋值的时候,调用Record,如果没有id的话,就调用Ext.data.Record.id,这时候就把phantom改为TRUE了。所以我们如果指定了idProperty的话,不给id赋值的话,我们第一次修改action会成为create,而第二次和第二次以后就是update了。

 

PS:其实按照ext的说明文档来,phantom属性的TRUE和FALSE作者用错了,事实上应该是相反的,大家看源代码就明白了,估计ext的作者也搞混了

 

      我们暂时把客户端指定的id为‘Id’服务器的id字段为‘sqlId’,正是由于store可以自动生成id,所以在服务器对数据的增删改操作就有一定的问题了,如果我们在load的时候就给指定的idProperty赋于服务器上的sqlId的话,我们对其进行修改,删除的操作还好,但是添加记录就会有问题了,store自动生成了一个Id而且你还不能改动,这样客户端的Id和服务器的sqlId就不一致了,后续操作就会出问题。

      有一种解决方案是:在服务器做一个字典,给客户端指定的‘Id’和服务器的‘sqlId’做一一对应,在客户端load的时候多给定一个id用来存储服务器的‘sqlId’,这样的话,你可以在服务器操作的时候使用sqlId,也就不会出错了,但关键问题是store在增加,修改的时候会把整条记录发送到服务器,唯独删除操作的时候,他只发送指定的idProperty,这样删除又成问题了。

 

      你可能会问为什么不用客户端生成的id直接当成服务器的id,这有两个原因:

【1】当多用户操作的时候,在各个客户端可能会生成相同的id

【2】客户端生成的id为string类型,SQL服务器对数字类型的字段查询效率要高于查询string类型的字段

 

      最终采取的解决方案是在在创建record的时候,绕过store直接存储到服务器上,通过服务器返回的id再给store中添加一条记录,这时候用的方法也不是add,因为你用add的话,store又会自动向服务器发送一个create的方法,这就会产生两条相同的记录,使用loadData方法可以在原有数据上添加数据

 

 

 

【附注:Ext 3.0 - API Documentation】:

 

phantom : Boolean

false when the record does not yet exist in a server-side database (see markDirty). Any record which has a real database pk set as its id property is NOT a phantom -- it's real.

 

idProperty : String

[id] Name of the property within a row object that contains a record identifier value. Defaults to id

 

loadData( Object data, [Boolean append] ) : void 

Loads data from a passed data block and fires the load event. A Reader which understands the format of the data must have been configured in the constructor.

  • data : Object

    The data block from which to read the Records. The format of the data expected is dependent on the type of Reader that is configured and should correspond to that Reader'sExt.data.Reader.readRecords parameter.

  • append : Boolean

    (Optional) true to append the new Records rather the default to replace the existing cache. Note: that Records in a Store are keyed by their id, so added Records with ids which are already present in the Store will replace existing Records. Only Records with new, unique ids will be added.

  • void

 

【附注:Ext 3.0源代码】:

Ext.data.DataReader.prototype = {

 

    buildExtractors : Ext.emptyFn,

 

    realize: function(rs, data){

        if (Ext.isArray(rs)) {

            for (var i = rs.length - 1; i >= 0; i--) {

                if (Ext.isArray(data)) {

                    this.realize(rs.splice(i,1).shift(), data.splice(i,1).shift());

                }

                else {

                    this.realize(rs.splice(i,1).shift(), data);

                }

            }

        }

        else {

            if (Ext.isArray(data) && data.length == 1) {

                data = data.shift();

            }

            if (!this.isData(data)) {

                throw new Ext.data.DataReader.Error('realize', rs);

            }

            this.buildExtractors();

            var values = this.extractValues(data, rs.fields.items, rs.fields.items.length);

            rs.phantom = false; // <-- That's what it's all about

            rs._phid = rs.id;  // <-- copy phantom-id -> _phid, so we can remap in Store#onCreateRecords

            rs.id = data[this.meta.idProperty];

            rs.data = values;

            rs.commit();

        }

    },

 

    update : function(rs, data) {

        if (Ext.isArray(rs)) {

            for (var i=rs.length-1; i >= 0; i--) {

                if (Ext.isArray(data)) {

                    this.update(rs.splice(i,1).shift(), data.splice(i,1).shift());

                }

                else {

                    this.update(rs.splice(i,1).shift(), data);

                }

            }

        }

        else {

            if (Ext.isArray(data) && data.length == 1) {

                data = data.shift();

            }

            if (!this.isData(data)) {

                rs.commit();

                throw new Ext.data.DataReader.Error('update', rs);

            }

            this.buildExtractors();

            rs.data = this.extractValues(Ext.apply(rs.data, data), rs.fields.items, rs.fields.items.length);

            rs.commit();

        }

    },

    isData : function(data) {

        return (data && Ext.isObject(data) && !Ext.isEmpty(data[this.meta.idProperty])) ? true : false;

    }

};

 

Ext.data.Record = function(data, id)

{ 

    this.id = (id || id === 0) ? id : Ext.data.Record.id(this);

    this.data = data || {};

};

 

Ext.data.Record.id = function(rec) 

{

    rec.phantom = true;

    return [Ext.data.Record.PREFIX, '-', Ext.data.Record.AUTO_ID++].join('');

};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值