Angular 7: Не удается добавить или обновить дочернюю строку: сбой ограничения внешнего ключа

#mysql #sql #angular #http

#mysql #sql #angular #http

Вопрос:

Я застрял на этой ошибке SQL и не понимаю, почему:

Таблица SQL

 CREATE DATABASE IF NOT EXISTS `cinego` /*!40100 DEFAULT CHARACTER SET latin1 */;
USE `cinego`;

-- Listage de la structure de la table cinego. salle
CREATE TABLE IF NOT EXISTS `salle` (
  `idSalle` int(11) NOT NULL AUTO_INCREMENT,
  `nom` varchar(50) DEFAULT NULL,
  `plan` blob,
  `nbPlace` int(11) DEFAULT NULL,
  `idCinema` int(11) DEFAULT NULL,
  `idTechno` int(11) DEFAULT NULL,
  PRIMARY KEY (`idSalle`),
  KEY `ref_salle_cinema` (`idCinema`),
  KEY `ref_salle_techno` (`idTechno`),
  CONSTRAINT `ref_salle_cinema` FOREIGN KEY (`idCinema`) REFERENCES `cinema` (`idCinema`),
  CONSTRAINT `ref_salle_techno` FOREIGN KEY (`idTechno`) REFERENCES `technologie` (`idTechno`)
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;
  

Это моя таблица, которая присутствует в базе данных Mysql.

Typescript

 @Component({
  selector: 'app-room-add',
  templateUrl: './room-add.component.html',
  styleUrls: ['./room-add.component.scss']
})
export class RoomAddComponent implements OnInit {
  cinema: Cinema = new Cinema();
  techno: Techno = new Techno();
  cinemas: Cinema[] = [];
  technos: Techno[] = [];
  addRoomForm = new FormGroup({
    name: new FormControl(''),
    blueprint: new FormControl(''),
    placelenght: new FormControl(''),
    cinema: new FormControl(''),
    techno: new FormControl(''),
  });   
  constructor(
    private roomService: RoomService,
    private cinemaService: CinemaService
  ) { }   
  ngOnInit() {
    this.cinemaService.getAllCinemas().subscribe(data => {
      this.cinemas = data['content'];
      console.log(this.cinemas);
    });
    this.roomService.getAllTechnos().subscribe(data => {
      this.technos = data['content'];
      console.log(this.technos);
    });
  }    
  onAdd(): void {
    const room: Room = this.addRoomForm.value;
    this.roomService.createRoom(room).subscribe(data => {
      console.log(data);
    });
    console.log(room);
  }    
}
  

Это мой код, лежащий в основе моего компонента Angular.

HTML

 <div class="container">
  <form class="room-add-form" [formGroup]="addRoomForm" enctype="application/x-www-form-urlencoded" (submit)="onAdd()">
    <mat-form-field class="room-add-full-width">
      <input matInput placeholder="Nom de la salle" formControlName="name">
    </mat-form-field>
    <mat-form-field class="room-add-full-width">
      <input matInput placeholder="Plan" formControlName="blueprint">
    </mat-form-field>
    <mat-form-field class="room-add-full-width">
      <input matInput type="number" placeholder="Nombre de place" formControlName="placelenght">
    </mat-form-field>
    <mat-form-field>
      <mat-select placeholder="Cinéma" formControlName="cinema">
        <mat-option *ngFor="let cinema of cinemas" [value]="cinema.id">
          {{cinema.name}}
        </mat-option>
      </mat-select>
    </mat-form-field>
    <mat-form-field>
      <mat-select placeholder="Technologie" formControlName="techno">
        <mat-option *ngFor="let techno of technos" [value]="techno.id">
          {{techno.name}}
        </mat-option>
      </mat-select>
    </mat-form-field>
    <button mat-button type="submit">Envoyer</button>
  </form>
</div>
  

Я уже пытался изменить события во время обновления / удаления в таблице, это не сработало.

В Postman запрос post отлично работает в моем API.

Версия Angular: 7.3.1

Редактировать

Я забыл добавить сообщение об ошибке

 Cannot add or update a child row: a foreign key constraint fails (`cinego`.`salle`, CONSTRAINT `ref_salle_cinema` FOREIGN KEY (`idCinema`) REFERENCES `cinema` (`id`))
  

Ответ №1:

Заполняется ли таблица cinema первой перед вставкой записей в таблицу salle? Я вижу, что cinema.idCinema является идентификатором ссылочного ключа для таблицы salle, поэтому пытаюсь его проверить. Исходя из ошибки, новая запись должна сначала присутствовать в таблице cinema, прежде чем вставлять запись в таблицу salle.

Комментарии:

1. Да, таблица cinema содержит эти же данные с правильным связанным идентификатором.

Ответ №2:

Я нашел решение своей проблемы, на этой стороне Angular, в моем сервисе, который извлекает HTTP-ответы.

 createRoom(item: Room): Observable<any> {
    return this.http.post<Room>(`${API_BASE_URL}/salle`, this.getFormUrlEncoded(item), {
      headers: new HttpHeaders()
        .set('Content-Type', 'application/x-www-form-urlencoded')
    });
  }
  

Я добавил функцию, которая вручную кодирует результаты формы в FormUrlEncode.

 getFormUrlEncoded(toConvert) {
    const formBody = [];
    // tslint:disable-next-line: forin
    for (const property in toConvert) {
      const encodedKey = encodeURIComponent(property);
      const encodedValue = encodeURIComponent(toConvert[property]);
      formBody.push(encodedKey   '='   encodedValue);
    }
    return formBody.join('amp;');
  }