How to enable cascade for only one model

1

By default EF6 is enabled to cascade models, until we use the following convention:

    modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

According to my research it does not allow deleting the cascade.

I have a model:

public class Cliente {

   public ICollection<Contato> Contatos {get;set;}
   public ICollection<Contrato> Contratos {get;set;}
   public ICollection<Funcionario> Funcionarios {get;set;}
   public ICollection<Fornecedor> Fornecedores {get;set}
   etc...
}

My Model Client, there are many lists, but I would like it if it has nothing in any of the lists, but only in the Contacts list, it can be deleted cascade, avoiding errors ... if it has data besides the Contacts list, it will give error ...

The idea is:

If Customer only has the Contacts list as a reference, then it can delete everything, Customer and its Contacts

If he has other links, then he can not delete them.

Reason:

I think I would lose a lot in performance if I were to check all the lists before removing them ... and also, it may be the reverse and I will not have the list, but it will reference ...

Is there a way to enable cascade for just one property?

    
asked by anonymous 26.01.2015 / 15:59

3 answers

1

Regardless of whether you have the conventions in the template (and some may not be removed) you can, of course, enable cascade as you like, see:

public class Client
{
    public int Id { get; set; }

    public string Name { get; set; }

    public virtual IList<Contact> Contacts { get; set; }

    public virtual IList<Employee> Employees { get; set; }
}

public class Employee
{
    public int Id { get; set; }

    public string Name { get; set; }
    public int ClientId { get; set; }

    public Client Client { get; set; }
}

public class Contact
{
    public int Id { get; set; }

    public int ClientId { get; set; }

    public Client Client { get; set; }
}

public class MyContext : DbContext
{
    public DbSet<Client> Clients { get; set; }

    public DbSet<Employee> Employees { get; set; }

    public DbSet<Contact> Contacts { get; set; }

    public MyContext()
    {

    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // com cascade
        modelBuilder.Entity<Contact>()
            .HasRequired(r => r.Client)
            .WithMany(t => t.Contacts)
            .WillCascadeOnDelete(true);

        // sem cascade
        modelBuilder.Entity<Employee>()
            .HasRequired(r => r.Client)
            .WithMany(t => t.Employees)
            .WillCascadeOnDelete(false);

        base.OnModelCreating(modelBuilder);
    }
}

Do not worry about the OneToManyCascadeDeleteConvention convention, it only applies to properties that have not been previously configured:

// trecho do código da convenção OneToManyCascadeDeleteConvention 
var configuration = edmDataModelItem.GetConfiguration() as NavigationPropertyConfiguration;

if ((configuration != null)
    && (configuration.DeleteAction != null))
{
    return;
}

Reference: OneToManyCascadeDeleteConvention

Note the configuration of the tables after creating a migration:

CreateTable(
    "dbo.Contacts",
    c => new
        {
            Id = c.Int(nullable: false, identity: true),
            ClientId = c.Int(nullable: false),
        })
    .PrimaryKey(t => t.Id)
    .ForeignKey("dbo.Clients", t => t.ClientId, cascadeDelete: true)
    .Index(t => t.ClientId);

CreateTable(
    "dbo.Employees",
    c => new
        {
            Id = c.Int(nullable: false, identity: true),
            Name = c.String(),
            ClientId = c.Int(nullable: false),
        })
    .PrimaryKey(t => t.Id)
    .ForeignKey("dbo.Clients", t => t.ClientId)
    .Index(t => t.ClientId);
    
02.02.2015 / 18:03
0

My application put the following commands and solve the problem you reported:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); 
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();

base.OnModelCreating(modelBuilder);
}

Do this that will solve.

    
26.01.2015 / 16:29
0

Cascade delete exists in two ways: the cascade you apply to FK on the bank itself and the CAS cascade.

So you have the following options:

1) The traditional FK in the database with cascade delete. So the bank takes care of deleting related records, regardless of whether these records are loaded and tracked by EF.

2) Change the relationship in your template to reflect the requirement.

public class Contato {

   [Required]
   public Cliente Cliente {get;set;}
}

To do this, client contacts must be EF-loaded.

    
01.02.2015 / 20:35