How to enable single-model Cascade

Asked

Viewed 220 times

1

By default EF6 is enabled to delete in Select models, until we use the following convention:

    modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

According to my searches it does not allow to delete the.

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 Client Model, there are numerous lists, but I would like that if it has nothing, in any of the lists, but have only in the Contacts list, it can be deleted in Scade, avoiding errors... Then if case, it has data beyond the Contacts list, it will give error...

The idea is:

If the Customer has only the Contact List as a reference, then he can delete everything, Client and his Contacts

If he has other ties, then he cannot exclude.

Motive:

I think I would lose a lot in performance, if I went to consult all the lists before removing...and also, could be reversed and I will not have the list, but there will be reference...

There is a way to enable Cascade for only one property ?

3 answers

1


Whether you have conventions in the template (and some may not be removed) you can, yes, enable Calendar as you prefer, see only:

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);
    }
}

Don’t worry about the convention OneToManyCascadeDeleteConvention, it only applies to properties that were not 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 how the tables configuration looks 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);

0

The Cascade delete exists in two ways: the Cascade you apply to FK in the database itself and the EF Cascade.

So you have the following options:

1) The traditional FK in the database with delete Cascade. Thus the bank takes care to delete the related records, regardless of whether these records are loaded and trackeados by the EF.

2) Change the relationship in your model to reflect the obligation.

public class Contato {

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

For this the client’s contacts will have to be loaded by the EF.

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 it that will solve.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.