Home > Back-end >  How can I perform nested deletes gorm Golang?
How can I perform nested deletes gorm Golang?

Time:10-27

I have a table Customers with Cars, and Cars has Services. When I delete the Car I also want to delete the Services from the database And when I delete the Customer I want to be able to delete Customer, its Cars, Its Services.

I tried the following to delete Car and Services related to the Car, but it only deletes the Car from the database, how do I delete both Cars and its Services?

type Customer struct {
    gorm.Model

    FirstName string
    LastName  string
    Phone     string `gorm:"typevarchar(100);unique_index"`
    Cars      []Car  `gorm:"constraint:OnDelete:CASCADE;"`
}

type Car struct {
    gorm.Model

    Make       string
    Modelo     string
    Color      string
    VinNumber  string     `gorm:"typevarchar(100);unique_index"`
    Services   []*Service `gorm:"constraint:OnDelete:CASCADE;"`
    CustomerId int
}

type Service struct {
    gorm.Model

    Comment string
    Miles   string
    CarId   int
}

//endpoints
//delete customer
func deleteCustomer(w http.ResponseWriter, r *http.Request) {
    params := mux.Vars(r)

    setupResponse(&w, r)
    if (*r).Method == "OPTIONS" {
        return
    }

    var customer Customer
    db.First(&customer, params["id"])
    db.Unscoped().Delete(&customer)

    json.NewEncoder(w).Encode(&customer)
}

func deleteCar(w http.ResponseWriter, r *http.Request) {
    setupResponse(&w, r)
    if (*r).Method == "OPTIONS" {
        return
    }

    params := mux.Vars(r)

    var car Car
    db.First(&car, params["id"])
    db.Select("Services").Unscoped().Delete(&car)
    json.NewEncoder(w).Encode(&car)
}
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

I already tried most of what I seen in StackOverflow and the docs but nothing seems to work so far.

CodePudding user response:

After reading the docs and a bunch of StackOverflow answers nothing really worked for me. The docs and/or StackOverflow suggested I add constraints when I migrated the models, or/and add the constraints to the structs gorm:"constraint:OnDelete:CASCADE;" , I also tried db.Select("cars").Delete(&customers) with no success. This is how I went about it, not sure if it's the best practice but it deletes its related records from the database. I updated the deleteCustomer and deleteCar endpoint like this:

//delete customer
func deleteCustomer(w http.ResponseWriter, r *http.Request) {
    params := mux.Vars(r)

    setupResponse(&w, r)
    if (*r).Method == "OPTIONS" {
        return
    }

    var customer Customer
    var cars []Car

    db.First(&customer, params["id"])
    db.Model(&customer).Related(&cars)

    deleteServicesSqlStatement := `
        DELETE FROM services
        WHERE car_id = $1;`

    for i, car := range cars {
        fmt.Println(i, car.ID)
        err := db.Exec(deleteServicesSqlStatement, car.ID).Error
        if err != nil {
            fmt.Println(err)
        }

    }

    DeleteCarsSqlStatement := `
        DELETE FROM cars
        WHERE customer_id = $1;`

    err := db.Exec(DeleteCarsSqlStatement, params["id"]).Error
    if err != nil {
        fmt.Println(err)
    }

    db.Debug().Unscoped().Delete(&customer)
    json.NewEncoder(w).Encode(&customer)

}


//delete car
func deleteCar(w http.ResponseWriter, r *http.Request) {
    //handle CORS
    setupResponse(&w, r)
    if (*r).Method == "OPTIONS" {
        return
    }

    params := mux.Vars(r)

    var car Car
    db.First(&car, params["id"])

    sqlStatement := `
        DELETE FROM services
        WHERE car_id = $1;`

    err := db.Exec(sqlStatement, params["id"]).Error

    if err != nil {
        fmt.Println(err)
    }

    db.Debug().Unscoped().Delete(&car)
    json.NewEncoder(w).Encode(&car)
}
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related