Oleg Sh
Oleg Sh

Reputation: 9013

EF : why child records are not deleted

I have the following structure:

public partial class Driver 
{
    public int ID { get; set; }
    //....

    #region Vistracks Required Fields

    public virtual ProblemSyncToVistracksDriver ProblemSyncToVistracksDriver { get; set; }

    #endregion
}


public partial class ProblemSyncToVistracksDriver
{
    [Key, ForeignKey("Driver")]
    public int DriverId { get; set; }
    public virtual Driver Driver { get; set; }

    public int? ResponseCode { get; set; }
    public string Message { get; set; }
    public string Description { get; set; }
    public bool IsServerError { get; set; }
    public DateTime DateAdded { get; set; }
}


modelBuilder.Entity<ProblemSyncToVistracksDriver>()
    .HasRequired(s => s.Driver)
    .WithOptional(ad => ad.ProblemSyncToVistracksDriver)
    .WillCascadeOnDelete(false);

then I try to remove a record from ProblemSyncToVistracksDriver for concrete driver:

        var driver = await (from i in _db.Drivers where i.AspNetUser.UserName.Equals(model.Email, StringComparison.InvariantCultureIgnoreCase) select i).FirstOrDefaultAsync();
        if (driver == null)
            throw new NullReferenceException();

        driver = mapper.Map<VistrackDriverInfoDomain, Infrastructure.Asset.Driver>(model, driver);
        driver.IsVistracksAdded = true;
        driver.VistracksDateSync = DateTime.Now;
        driver.ProblemSyncToVistracksDriver = null;

        _db.Entry(driver).State = EntityState.Modified;
        await _db.SaveChangesAsync();

no errors, all other changes are saved. But record in ProblemSyncToVistracksDriver is not deleted. Why and how to fix it?

Upvotes: 0

Views: 63

Answers (2)

Harald Coppoolse
Harald Coppoolse

Reputation: 30464

In your model, you specified:

modelBuilder.Entity<ProblemSyncToVistracksDriver>()
    .HasRequired(s => s.Driver)
    .WithOptional(ad => ad.ProblemSyncToVistracksDriver)
    .WillCascadeOnDelete(false);

This specification indicates that every ProblemSyncToVistrackDriver object belongs to exactly one Driver, not zero, not two: exactly one. This Driver can be found in property Driver.

The Driver that you will find in property Driver has an optional property ProblemSyncToVistracksDriver. This means, that if that property is null, entity framework might assume that there is no ProblemSyncToVistrackDriver that belongs to this Driver.

What you did, is that you specified a proper one-to-zero-ore-one relation. Every Driver has zero or one ProblemSyncToVistrackDriver, every ProblemSyncToVistrackDriver belongs to exactly one Driver.

If you've got a Driver, and you'll set its ProblemSyncToVistrackDriver to zero, then what you are saying is that this Driver has no ProblemSyncToVistrackDriver anymore. Normally, CascadeOnDelete would have taken care that the former ProblemSyncToVistrackDriver of this Driver would be deleted. You specified that you don't want this automatic deletion, hence the ProblemSyncToVistrackDriver is not deleted. That's why it is not deleted.

If you specify that you want manual-deletion, you'll have to delete the item yourself.

Upvotes: 1

Lucian Bumb
Lucian Bumb

Reputation: 2881

In order to remove a child record you need first to get it from database and then you can set it to null:

var driver=_db.Drivers.Include(x=>x.ProblemSyncToVistracksDrivers)
.FirstOrDefaultAsync(x=>x.AspNetUser.UserName.Equals(model.Email, StringComparison.InvariantCultureIgnoreCase));
driver.ProblemSyncToVistracksDriver = null;
 await _db.SaveChangesAsync();

more explanations you can find here similar question

Upvotes: 1

Related Questions