Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delete an owned entity on update? #135

Open
cryo75 opened this issue Feb 26, 2015 · 5 comments
Open

Delete an owned entity on update? #135

cryo75 opened this issue Feb 26, 2015 · 5 comments
Assignees

Comments

@cryo75
Copy link

cryo75 commented Feb 26, 2015

I have the following model:

public class Address
{
    public int Id {get; set;}
    public string Street {get; set;}
    public int PostCodeId {get; set;}
    public PostCode PostCode {get; set;}
    //etc...
}

public class Customer
{
    public int Id {get; set;}
    public string Name {get; set;}
    public int AddressId {get; set;}
    public virtual void Address Address {get; set;}
}

I load an existing customer with his address, and I want to delete address, so I do:

customer.Address = null;

customer = dbContext.UpdateGraph<Customer>
                (entity, map => map.OwnedEntity(x => x.Address, with => with.AssociatedEntity(x => x.PostCode)));   

The customer's address id is set to null correctly. However the address is not being deleted from the db. How can I delete the owned entity from the db?

@josh-dastmalchi
Copy link
Contributor

This is most likely an EF-configuration issue. The default relation in EF for a one-way nav property is one-to-many. (It doesn't know Address is unique to this customer)

Try setting your config to:
HasRequired(c=> c.Address).WithRequired()
or
HasOptional(c=> c.Address).WithRequired()
depending on whether or not Address is optional for a Customer.

@cryo75
Copy link
Author

cryo75 commented Mar 6, 2015

I used HasOptional(c => c.Address).WithRequired().

However, it doesn't work because the address is now not being set in the customer although the correct SQL statement is being used.

@cryo75
Copy link
Author

cryo75 commented Mar 19, 2015

This issue is still not solved. Could it be because I'm not using EF's default naming conventions?

@sundeepyama
Copy link

I am having the same issue.

@ghost ghost added the potential bug label Jul 22, 2015
@MilanRaval
Copy link

MilanRaval commented May 3, 2022

I had similar issues, fixed both in OwnedEntityGraphNode's Update method below..

  1. setting new value null was not deleting the record - fixed it by adding "changeTracker.RemoveItem(dbValue);" when newValue is null - first IF

  2. replace value of child by setting a new instance was not deleting the old record - fix it by adding "changeTracker.RemoveItem(dbValue);" when new value has id = 0 and old value has id > 0

public override void Update<T>(DbContext context, T persisted, T updating)
        {
            var dbValue = GetValue<object>(persisted);
            var newValue = GetValue<object>(updating);

            if (dbValue == null && newValue == null)
                return;

            // Merging options
            // 1. No new value, set value to null. entity will be removed if cascade rules set.
            // 2. If new value is same as old value lets update the members
            // 3. Otherwise new value is set and we don't care about old dbValue, so create a new one.
            if (newValue == null)
            {
                SetValue(persisted, null);
                RemoveElement(context, dbValue);
                return;
            }

            if (dbValue != null && IsKeyIdentical(context, newValue, dbValue))
                UpdateValuesWithConcurrencyCheck(context, newValue, dbValue);
            else
            {
                var newEntity = CreateEntityKey(context, newValue);
                var dbEntity = dbValue != null ? CreateEntityKey(context, dbValue) : null;
                if (dbEntity != null &&
                    ((int)newEntity.EntityKeyValues[0].Value <= 0
                        && (int)dbEntity.EntityKeyValues[0].Value > 0))
                {
                    RemoveElement(context, dbValue);
                }

                dbValue = CreateNewPersistedEntity(context, persisted, newValue);
            }

            AttachCyclicNavigationProperty(context, persisted, newValue);

            // if (dbValue != null) // make an error throw or not?
            foreach (var childMember in Members)
                childMember.Update(context, dbValue, newValue);
        }

        private void RemoveElement(DbContext context, object dbItem)
        {
            context.Set(ObjectContext.GetObjectType(dbItem.GetType())).Remove(dbItem);
        }

Old version of code

public override void Update<T>(IChangeTracker changeTracker, IEntityManager entityManager, T persisted, T updating)
        {
            var dbValue = GetValue<object>(persisted);
            var newValue = GetValue<object>(updating);

            if (dbValue == null && newValue == null)
            {
                return;
            }

            // Merging options
            // 1. No new value, set value to null. entity will be removed if cascade rules set.
            // 2. If new value is same as old value lets update the members
            // 3. Otherwise new value is set and we don't care about old dbValue, so create a new one.
            if (newValue == null)
            {
                SetValue(persisted, null);
                // fix - 1) setting new value null was not deleting the record
                changeTracker.RemoveItem(dbValue);
                return;
            }


            if (dbValue != null && entityManager.AreKeysIdentical(newValue, dbValue))
            {
                changeTracker.UpdateItem(newValue, dbValue, true);
            }
            else
            {
                // fix - 2) replace value of child by setting a new instance was not deleting the old record
                var newEntity = entityManager.CreateEntityKey(newValue);
                var dbEntity = dbValue != null ? entityManager.CreateEntityKey(dbValue) : null;
                if (dbEntity != null &&
                    ((int)newEntity.EntityKeyValues[0].Value == 0
                        && (int)dbEntity.EntityKeyValues[0].Value > 0))
                {
                    changeTracker.RemoveItem(dbValue);
                }
               

                dbValue = CreateNewPersistedEntity(changeTracker, persisted, newValue);
            }

            changeTracker.AttachCyclicNavigationProperty(persisted, newValue, GetMappedNaviationProperties());

            foreach (var childMember in Members)
            {
                childMember.Update(changeTracker, entityManager, dbValue, newValue);
            }
        }

@JonathanMagnan JonathanMagnan self-assigned this May 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

5 participants