Pregunta

I have been working on a project and I'm trying to get the cascade delete to kick in. I have a model below I use for comments. These comments can have replies that come off of them that call the comment class. What I'm trying to do is to make it delete all the replies that can flow off the comment.

Comment -> Reply -> Reply -> Reply -> so on.

If I'm going about this in the wrong direction, please let me know. I have tried to research into this but all I come up with is One-to-One and One-Many cascade codes. I'm using CodeFirst with MVC 4 to build my project.

Edited

public class Comment
    {
        // Properties
        public long Id { get; set; }

        [Required]
        [StringLength(250, ErrorMessage = "{0} must be between {1} and {2} characters", MinimumLength = 2)]
        public string Body { get; set; }

        [Required]
        public DateTime CreateDate { get; set; }

        [Required]
        [InverseProperty("Comments")]
        public User Author { get; set; }

        [InverseProperty("CommentCount")]
        public Blog Blog { get; set; }

        public bool Hidden { get; set; }

        public long RepliesId { get; set; }

        [InverseProperty("Replies")]
        public virtual Comment Comments { get; set; }

        [InverseProperty("Comments")]
        public virtual ICollection<Comment> Replies { get; set; }

        public virtual ICollection<Vote> Votes { get; set; }

        public Comment()
        {
            CreateDate = DateTime.UtcNow;
            Hidden = false;
        }
    }

Here is my DataContextInitializer

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Comment>().HasMany(i => i.Replies)
            .WithOptional(i => i.Comments)
            .HasForeignKey(i => i.RepliesId)
            .WillCascadeOnDelete();
    }
¿Fue útil?

Solución

You could enable cascade delete with something like this (i.e. you need to manually set the relationship)...

modelBuilder.Entity<Comment>()
    .HasOptional(x => x.Replies)
    .WithOptionalDependent()
    .WillCascadeOnDelete(true);

However, it won't do you much good - as Update-Database will fail with something like...

A foreign key constraint that has an UPDATE or a DELETE CASCADE rule, and self-references a column in the same table, is not allowed.

i.e. that works on FK-s that are connecting different tables - but not if self-referencing.

See this post with some more relevant info - especially the comment that mentions

"you need to drop the FK and manually create it with cascade delete in your DatabaseInitializer"

EF4 Code first - delete all children when deleting parent from db?

In short, I don't think there is a straight-forward solution - but some manual setup (initializer etc.) is required (I haven't tried it). Or try to reorganize, flatten the relationships a bit (I haven't thought much, just throwing here some pretty general approaches).


Just FYI - even though I think it's not going to get you anywhere (see above)...

public class Comment
{
    // Properties
    public long Id { get; set; }

    //[Required]
    //[StringLength(250, ErrorMessage = "{0} must be between {1} and {2} characters", MinimumLength = 2)]
    public string Body { get; set; }

    [Required]
    public DateTime CreateDate { get; set; }

    // [Required]
    // [InverseProperty("Comments")]
    public MyUser Author { get; set; }

    // [InverseProperty("CommentCount")]
    public Blog Blog { get; set; }

    public bool Hidden { get; set; }

    public virtual ICollection<Comment> Replies { get; set; }
    public virtual ICollection<Vote> Votes { get; set; }

    public Comment()
    {
        CreateDate = DateTime.UtcNow;
        Hidden = false;
    }
}

modelBuilder.Entity<Comment>()
    .HasOptional(x => x.Replies)
    .WithOptionalDependent()
    .WillCascadeOnDelete(true);

This should work fine if you let it 'not cascade'. Otherwise fails.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top