yii2-relation-trait icon indicating copy to clipboard operation
yii2-relation-trait copied to clipboard

The object being updated is outdated.

Open strtob opened this issue 6 years ago • 5 comments

Hi,

I've built a crud app with mootensai/yii2-enhanced-gii, there are related tables by foreign keys (n:1, n:m).

In the case I got an validation error, after pressing update a second time the app throw the following error:

`Stale Object Exception – yii\db\StaleObjectException The object being updated is outdated.

1. in /home/none/work/rebase/vendor/yiisoft/yii2/db/BaseActiveRecord.php at line 813
804805806807808809810811812813814815816817818819820821822

                            if ($lock !== null) {
            $values[$lock] = $this->$lock + 1;
            $condition[$lock] = $this->$lock;
        }
        // We do not check the return value of updateAll() because it's possible
        // that the UPDATE statement doesn't change anything and thus returns 0.
        $rows = static::updateAll($values, $condition);
 
        if ($lock !== null && !$rows) {
            throw new StaleObjectException('The object being updated is outdated.');
        }
 
        if (isset($values[$lock])) {
            $this->$lock = $values[$lock];
        }
 
        $changedAttributes = [];
        foreach ($values as $name => $value) {
            $changedAttributes[$name] = isset($this->_oldAttributes[$name]) ? $this->_oldAttributes[$name] : null;
                

2. in /home/none/work/rebase/vendor/yiisoft/yii2/db/ActiveRecord.php at line 631 – yii\db\BaseActiveRecord::updateInternal(null)
3. in /home/none/work/rebase/vendor/yiisoft/yii2/db/BaseActiveRecord.php at line 681 – yii\db\ActiveRecord::update(true, null)
4. in /home/none/work/rebase/vendor/mootensai/yii2-relation-trait/RelationTrait.php at line 166 – yii\db\BaseActiveRecord::save()
160161162163164165166167168169170171172

                            /* @var $this ActiveRecord */
        $db = $this->getDb();
        $trans = $db->beginTransaction();
        $isNewRecord = $this->isNewRecord;
        $isSoftDelete = isset($this->_rt_softdelete);
        try {
            if ($this->save()) {
                $error = false;
                if (!empty($this->relatedRecords)) {
                    /* @var $records ActiveRecord | ActiveRecord[] */
                    foreach ($this->relatedRecords as $name => $records) {
                        if (in_array($name, $skippedRelations))
                            continue;
                

5. in /home/none/work/rebase/controllers/SalesLeadController.php at line 145 – app\models\base\SalesLead::saveAll()

`

anybody an idea what's the problem?

Cheers!

strtob avatar Mar 14 '19 20:03 strtob

yiisoft/yii2/db/BaseActiveRecord.php What version of yii are you using? Line 81 of 2.16.1 looks like this: if ($lock !== null && !$rows) {

Can you try it on 2.16.1 without breaking your project?

Can you think of a test I could do to verify the behavior you want is working?

danabyrd avatar Mar 16 '19 05:03 danabyrd

Thank you for your help, unfortunately, I still have the problem also with v 2.16.1

` Stale Object Exception – yii\db\StaleObjectException The object being updated is outdated.

1. in C:\Users\none\work\rebase\vendor\yiisoft\yii2\db\BaseActiveRecord.php at line 813
804805806807808809810811812813814815816817818819820821822

                            if ($lock !== null) {
            $values[$lock] = $this->$lock + 1;
            $condition[$lock] = $this->$lock;
        }
        // We do not check the return value of updateAll() because it's possible
        // that the UPDATE statement doesn't change anything and thus returns 0.
        $rows = static::updateAll($values, $condition);
 
        if ($lock !== null && !$rows) {
            throw new StaleObjectException('The object being updated is outdated.');
        }
 
        if (isset($values[$lock])) {
            $this->$lock = $values[$lock];
        }
 
        $changedAttributes = [];
        foreach ($values as $name => $value) {
            $changedAttributes[$name] = isset($this->_oldAttributes[$name]) ? $this->_oldAttributes[$name] : null;                  

`

error_log dump:

  • $lock = db_lock (this is my lock column name)
  • $rows = 0

the comment of the BaseActiveRecord is like this:

// We do not check the return value of updateAll() because it's possible // that the UPDATE statement doesn't change anything and thus returns 0. $rows = static::updateAll($values, $condition);

But why should this condition ($lock is the column name && no updates) throws an error?

strtob avatar Mar 18 '19 21:03 strtob

Anybody got any idea where is the problem? :-(

strtob avatar Mar 21 '19 11:03 strtob

@strtob I don't know the cause yet. I've setup a test harness to run an x-debug trace on my database.

Thanks for the information you have sent so far. I will let you know what I find.

danabyrd avatar Mar 22 '19 05:03 danabyrd

Thank you :-)

strtob avatar Mar 22 '19 06:03 strtob