FluentApi do kaskadowego usuwania ASP.NET MVC

0

Jak za pomoca modelBuilder.Entity ustawic kaskadowe usuwanie.
Chcę usunąć jeden wpis z tabeli Rezerwacja, jak powinienem zaimplementować fluentApi przy pomocy modelBuilder.Entity?
Modele mogą zawierać błędy, bo napisałem w biegu.

class Rezerwacja
{
 int  RezerwacjaID
 ICollection<RezerwacjaPokoj> pokoje{get;set;}
 virtual Uzytkownik uzytkownik {get;set;
}

class RezerwacjaPokoj
{
 int _id;
 virtual Rezerwacja rezerwacja {get;set;}
 virtual Pokoj pokoj {get;set;}
}
class Pokoj
{
 int  _id;
ICollection<RezerwacjaPokoj> pokoje{get;set;}
 
}

class Uzytkownik
{
[Foreign key=RezerwacjaID]
 int _id;
string imie;
string nazwisko;
}
0

Rezerwacja wiele do wiele z pokoje, tabela posrednia (rezerwacjapokoj) i relacja jeden do jeden z Uzytkownik

0

Kaskadowe usuwanie ustawiasz na bazie - w ef opisujesz to tylko po to by wygenerowal Ci ewentualnie poprawny skrypt tworzacy baze.

0

WillCascadeOnDelete

You can configure cascade delete on a relationship by using the WillCascadeOnDelete method. If a foreign key on the dependent entity is not nullable, then Code First sets cascade delete on the relationship. If a foreign key on the dependent entity is nullable, Code First does not set cascade delete on the relationship, and when the principal is deleted the foreign key will be set to null.

0

Cascade delet robione jest przez baze - EF tego nie moze zrobic. EF tylko przygotowuje model i jego obsluge + skrypt do generacji bazy. Jesli chcesz miec kasowanie kaskadowe to musisz to ustawic na bazie - to wszystko.

0

@jacek.placek - masz racje ze sie upierasz - jednak EF obsluguje kaskadowe kasowanie. Bylem pewny ze to nie dziala - bo kiedys nie dzialalo ale byc moze byla to wersja 4.1 albo jeszcze wczesniejsza albo zwyczajnie cos mi sie pochrzanilo. Co do ustawien to cos takiego powinno robic.

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<RezerwacjaPokoj>()
            .HasRequired<Rezerwacja>(s => s.rezerwacja)
            .WithMany()
            .WillCascadeOnDelete(false);
    }

Z drugiej strony to jesli elementy ktore maja byc usuniete przez kaskadowe kasowenie nie beda zaciagniete (nawet gdy jest lazyloading) to baza zwrocil blad - wiec koniec koncow lepiej zadziala to gdy ustawimy kasowanie kaskadowe na bazie.

0

No chyba znowu nie.
tylko trzeba wpisać .WillCascadeOnDelete(true);

EF6.1.3

Tworzy się ładna definicja w DB z Delete Rule - Cascade - czyli to samo co ustawiłbyś w bazie.
I jak wywalisz rodzica contect.Entity.Remove()
To usunie też dzieci nawet przy wyłączonym LazyLoading (można zobaczyć w debugerze, ze nie ładuje dzieci). Aż sprawdziłem i tak to działa.

W drugim using widać, ze Person nie ładuje adresów.

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EF_Cascade
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var db = new EFContext()) {

                var a = new Address { Adres = "adres1" };
                var a1 = new Address { Adres = "adres2" };
                var p = new Person { Name = "Name 1" };
                p.Adresses.Add(a);
                p.Adresses.Add(a1);

                db.Persons.Add(p);

                db.SaveChanges();

            }

            using (var db = new EFContext())
            {
                
                var pd = db.Persons.FirstOrDefault(x => x.Name == "Name 1");
                db.Persons.Remove(pd);

                db.SaveChanges();
            }
        }
    }

    public class Person
    {
        public Person()
        {
            Adresses = new List<Address>();
        }
        public int Id { get; set; }
        public string Name { get; set; }

        public virtual ICollection<Address> Adresses { get; set; }
    }

    public class Address
    {
        public int Id { get; set; }
        public virtual Person Person { get; set; }

        public string Adres { get; set; }


    }

    public class EFContext : DbContext
    {
        public EFContext() : base("name=ef_cascadedeelte")
        {
            //Configuration.ProxyCreationEnabled = false;
            Configuration.LazyLoadingEnabled = false;
            //Database.SetInitializer<SprayerDataContext>(new DropCreateDatabaseIfModelChanges<SprayerDataContext>());
            //Database.SetInitializer<SprayerDataContext>(new CreateDatabaseIfNotExists<SprayerDataContext>());
        }

        public DbSet<Person> Persons { get; set; }
        public DbSet<Address> Addresses { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {

            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<Address>()
                .HasOptional<Person>(x=>x.Person)
                .WithMany(x=>x.Adresses)
                .WillCascadeOnDelete(true);
        }
    }


}

0

W Twoim przykladzie to nie EF odpowiada za kasowanie kaskadowe tylko baza. Wejdz na baze i wykasuj klucz address->person a potem dodaj taki sam bez ustawienia na delete cascade. Jak to zrobisz Twoj program zwroci blad podczas kasowania osoby. EF jednak nie obsluguje w sensowny sposob tego - bedziesz musial to ustawiac na bazie.

0

O masz.
No pewnie, że baza ale o to wlasnie chodzi w WillCascadeOnDelete we fluent zeby zdefiniwać takie zachowanie bez ręcznego grzebania w bazie. Bo po jaki ... wtedy używać migracji jak grzebiesz recznie w bazie?
O to chodziło w pytaniu. Jak we fluent ustawic usuwanie kaskadowe.

A co do błędu po skasowaniu to chyba nie zwróci bo Person jest Optional i w bazie bedzie nullable ale nie sprawdzalem.

EDIT:
Faktycznie, jak się zmieni w bazie Delete Rule na NoAction to faktycznie wywali błąd a jak się zmieni na Set Null (co ma większy sens) to zostawi sierotę z nullem.

1 użytkowników online, w tym zalogowanych: 0, gości: 1