英文:
How to cascade (soft) delete has many relationships in GORM?
问题
我正在使用GORM实现一些删除功能。我的想法是级联删除,即当删除父行时,子行也会被删除。我尝试过使用delete with select。但它只删除了父记录。
func DeleteProject(db *gorm.DB, id uint) (Project, error) {
var project Project
if err := db.Select(clause.Associations).Delete(&project, id).Error; err != nil {
return Project{}, err
}
return project, nil
}
我有以下模型:
type Project struct {
ID uint `gorm:"primary_key" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"`
TicketNumber string `gorm:"size:6;unique;not null" json:"ticketnumber"`
Name string `json:"name"`
MailingList string `json:"mailinglist"`
Environment string `gorm:"not null" json:"environment"`
UserID uint `gorm:"index" json:"user_id"`
Diagrams []Diagram `json:"diagrams"`
}
type Diagram struct {
ID uint `gorm:"primary_key" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"`
Data string `json:"data"`
ProjectID uint `gorm:"index" json:"project_id"`
Instances []Instance `json:"instances"`
}
type Instance struct {
ID uint `gorm:"primary_key" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"`
Key uint `json:"key"`
DiagramID uint `gorm:"index" json:"diagram_id"`
}
一个项目可以有多个图表,一个图表可以有多个实例。但是当我运行DeleteProject
函数时,它只删除了Project
,而没有删除关联的图表和实例。
在这种情况下,我该如何删除一个项目及其关联的图表和实例?
英文:
I am implementing some delete functionality using GORM. My idea is to cascade delete where when the parent row is deleted the childern are deleted aswell. I have tried the delete with select. But it only deletes the parent record.
func DeleteProject(db *gorm.DB, id uint) (Project, error) {
var project Project
if err := db.Select(clause.Associations).Delete(&project, id).Error; err != nil {
return Project{}, err
}
return project, nil
}
I have the following model:
type Project struct {
ID uint `gorm:"primary_key" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"`
TicketNumber string `gorm:"size:6;unique;not null" json:"ticketnumber"`
Name string `json:"name"`
MailingList string `json:"mailinglist"`
Environment string `gorm:"not null" json:"environment"`
UserID uint `gorm:"index" json:"user_id"`
Diagrams []Diagram `json:"diagrams"`
}
type Diagram struct {
ID uint `gorm:"primary_key" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"`
Data string `json:"data"`
ProjectID uint `gorm:"index" json:"project_id"`
Instances []Instance `json:"instances"`
}
type Instance struct {
ID uint `gorm:"primary_key" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"deleted_at"`
Key uint `json:"key"`
DiagramID uint `gorm:"index" json:"diagram_id"`
}
Where a project can have multiple diagrams and a diagram can have multiple instances. But when I am running the DeleteProject
function it is only deleting the Project
and not the associated diagrams and instances.
How can I delete a project and it's associated diagrams and instances in this case?
答案1
得分: 2
我找到了一个解决方案,但我认为对于级联删除来说并不是最优的,至少解决了我的问题。我编写了以下代码:
首先是DeleteProject
函数,其中我循环遍历所有的Diagrams
并调用DeleteDiagram
函数,最后在删除项目之前还清除了与该项目的所有关联。
//删除项目及其关联
func DeleteProject(db *gorm.DB, id uint) (Project, error) {
project, err := GetProject(db, id)
if err != nil {
return Project{}, err
}
if len(project.Diagrams) > 0 {
for _, projectDiagram := range project.Diagrams {
_, err := DeleteDiagram(db, projectDiagram.ID)
if err != nil {
return Project{}, err
}
}
db.Model(&project).Association("Diagrams").Clear()
}
if err := db.Delete(&project, id).Error; err != nil {
return Project{}, err
}
return project, nil
}
DeleteDiagram
函数也是类似的,只是针对Instances
进行操作。
//删除图表及其关联
func DeleteDiagram(db *gorm.DB, id uint) (Diagram, error) {
var diagram, err = GetDiagram(db, id)
if err != nil {
return Diagram{}, err
}
if len(diagram.Instances) > 0 {
db.Model(&diagram).Association("Instances").Clear()
for _, diagramInstance := range diagram.Instances {
_, err := DeleteInstance(db, diagramInstance.ID)
if err != nil {
return Diagram{}, err
}
}
}
if err := db.Delete(&diagram).Error; err != nil {
return Diagram{}, err
}
return diagram, nil
}
希望对你有帮助。
英文:
I found an solution, but I think it is not optimal for cascade delete, it solved my problem at least. I've coded the following:
First the DeleteProject
function, where I loop over all Diagrams
and call the DeleteDiagram
function and finally I also clear all associations with this project before deleting the project.
//Delete a project and it's associations.
func DeleteProject(db *gorm.DB, id uint) (Project, error) {
project, err := GetProject(db, id)
if err != nil {
return Project{}, err
}
if len(project.Diagrams) > 0 {
for _, projectDiagram := range project.Diagrams {
_, err := DeleteDiagram(db, projectDiagram.ID)
if err != nil {
return Project{}, err
}
}
db.Model(&project).Association("Diagrams").Clear()
}
if err := db.Delete(&project, id).Error; err != nil {
return Project{}, err
}
return project, nil
}
The DeleteDiagram
does the same, but then with the Instances
//Delete a diagram and it's associations.
func DeleteDiagram(db *gorm.DB, id uint) (Diagram, error) {
var diagram, err = GetDiagram(db, id)
if err != nil {
return Diagram{}, err
}
if len(diagram.Instances) > 0 {
db.Model(&diagram).Association("Instances").Clear()
for _, diagramInstance := range diagram.Instances {
_, err := DeleteInstance(db, diagramInstance.ID)
if err != nil {
return Diagram{}, err
}
}
}
if err := db.Delete(&diagram).Error; err != nil {
return Diagram{}, err
}
return diagram, nil
}
Hope it helps.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论