CActiveRecord: update after insert not working

Hi!

After creating and save()ing an CActiveRecord, updates on the same object are not working.

I traced the problem to SQL commands with "WHERE id=NULL". It turned out that in CActiveRecord::update, the old primary key (_pk) ist not set.


            $this->updateByPk($this->getOldPrimaryKey(),$this->getAttributes($attributes));

Doing a manual reload via $a=MyModel::model()->findByPk($a->id); directly after the first $a->save() does solve all problems.

So I assume CActiveRecord::insert() does not properly setOldPrimaryKey(), which should be fixed.

I am using Yii Version 1.1rc December 13, 2009.

Are you trying to update your model in the afterSave() method?

Since the property $isNewRecord is set to false only after afterSave() method, I guess it may cause some problems.

http://www.yiiframework.com/forum/index.php?/topic/2982-ar-isnewrecord-and-aftersave

No, I don’t use afterSave. After quite some hours of work, I could reproduce the problem with the following minimal example.


Test1::model()->deleteAll();

Test2::model()->deleteAll();

$a = new Test1;

$a->text = 'orig';

$a->save();

#  $a = Test1::model()->findByPk($a->id);   # temporary workaround

$bb = new Test2;

$bb->save();

$a->text = 'changed';

$a->save();

die('Now look in the database. Instead of "changed", I see "orig" there.');



DB definition and models[spoiler]


CREATE TABLE IF NOT EXISTS `Test1` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `text` text NOT NULL,

  PRIMARY KEY (`id`)

);

CREATE TABLE IF NOT EXISTS `Test2` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  PRIMARY KEY (`id`)

);


class Test1 extends CActiveRecord {

    public static function model($className=__CLASS__) {

        return parent::model($className);

    }

}


class Test2 extends CActiveRecord {

    public static function model($className=__CLASS__) {

        return parent::model($className);

    }



[/spoiler]

I can confirm the problem. Right now I`m reloading the model after insert, this solves the problem.

I suggest this

$r->save();

$r->setPrimaryKey($r->primaryKey); //workaround

Hello,

i have the same problem. Have anyone solved it in a better way? If i load a model out of my database (innodb) then the flag isNewRecord is set to true but the data from the database is inside the model class. If i try to save the database returns that the pk is already in use because the ar model object does a insert instead of an update because the flag is wrong.

I can set the flag manually but by whole application has the same problem and this isn’t a sufficient solution.

regards

Martin

This solution work for me.

$this->$primaryKey is empty but not strongly equal null. So replace


$this->$primaryKey===null

with


empty($this->$primaryKey)

File:/framework/db/ar/CActiveRecord.php




public function insert($attributes=null)

	{

		if(!$this->getIsNewRecord())

			throw new CDbException(Yii::t('yii','The active record cannot be inserted to database because it is not new.'));

		if($this->beforeSave())

		{

			Yii::trace(get_class($this).'.insert()','system.db.ar.CActiveRecord');

			$builder=$this->getCommandBuilder();

			$table=$this->getMetaData()->tableSchema;

			$command=$builder->createInsertCommand($table,$this->getAttributes($attributes));

			if($command->execute())

			{

				

				$primaryKey = $table->primaryKey;

				if($table->sequenceName!==null)

				{

					//EDITED

					//if(is_string($primaryKey) && $this->$primaryKey===null){

					if(is_string($primaryKey) && empty($this->$primaryKey)){

				

						$this->$primaryKey=$builder->getLastInsertID($table);

					}else if(is_array($primaryKey))	{

						foreach($primaryKey as $pk)

						{

							

							if($this->$pk===null)

							{

								$this->$pk=$builder->getLastInsertID($table);

								break;

							}

						}

					}

				}

				$this->_pk=$this->getPrimaryKey();

				$this->afterSave();

				$this->setIsNewRecord(false);

				$this->setScenario('update');

				return true;

			}

		}

		return false;

	}