Question

I have an Entity. Mandate. Every mandate has a required:many relation to a Person (NavigationProperty). I use the DbContext API with (LazyLoadingEnabled, AutoDetectChangesEnabled, ValidateOnSaveEnabled, ProxyCreationEnabled)

Now I like to delete a Mandate entity. The mandate entities are loaded by another context with AsNoTracking().

message.Result.
    ObserveOn(On<DataComposition>.Scheduler).
    Where(r => r).
    Subscribe(_ =>
    {
        using (var unit = UnitOfWork.Begin())
        {
            var mandate = this.SelectedItem.OriginalEntity;

            this.mandateRepository.Attach(mandate);
            // mandate.Person.ToString();

            this.mandateRepository.Delete(mandate);

            unit.Commit();
        }

        this.List.RemoveOnUi(this.SelectedItem);
    });

Now during committing I get the following exception: Entities in 'CodeFirstContainer.Mandates' participate in the 'Mandate_Person' relationship. 0 related 'Mandate_Person_Target' were found. 1 'Mandate_Person_Target' is expected.

The delete works if I include the Person Property during the population/selection or if I visit the Property (lazyloading), but I DONT LIKE to materialize/hold many entities only for the deletion case and I DONT LIKE to trigger more than a single DELETE query to db!

Was it helpful?

Solution

The fact that, if you have the navigation property mandate.Person populated, the following SQL statement ...

delete [dbo].[Mandates]
where (([Id] = @0) and ([PersonId] = @1))

... is sent to the database, lets me think that the navigation property indeed must be populated with a person with the correct PersonId to delete the parent.

I have no idea why Entity Framework just doesn't send a delete statement with the primary key ...

delete [dbo].[Mandates]
where ([Id] = @0)

... as I had expected.

Edit

If the Mandate entity has a foreign key property PersonId for the Person navigation property, the expected SQL (the second above) is sent to the database. In this case the Person navigation property can be null and the value of the FK property PersonId doesn't matter.

Edit 2

If you don't want to introduce a FK property the way with the least DB-roundtrip-costs would probably be to fetch the person's Id and then create a dummy person with that key in memory:

// ...
var personId = context.Mandates
    .Where(m => m.Id == mandate.Id)
    .Select(m => m.Person.Id)
    .Single();

mandate.Person = new Person { Id = personId };

this.mandateRepository.Attach(mandate);
this.mandateRepository.Delete(mandate);
// ...
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top