mootensai / yii2-relation-trait

Yii 2 Models add functionality for load with relation, & transactional save with relation PLUS soft delete/restore feature
47 stars 45 forks source link

The object being updated is outdated. #60

Open strtob opened 5 years ago

strtob commented 5 years ago

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!

danabyrd commented 5 years ago

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?

strtob commented 5 years ago

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:

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 commented 5 years ago

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

danabyrd commented 5 years ago

@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.

strtob commented 5 years ago

Thank you :-)