Elad Benda
Elad Benda

Reputation: 36656

The relationship could not be changed .. the foreign-key properties is non-nullable

I'm trying to update an entity of type MamConfiguration_V1

which exsit already in the DB

It has few reference members (among them MamConfigurationToBrowser_V1)

  private void UpdateEfItem(MamConfiguration_V1 itemFromDb, MamConfiguration_V1 itemFromUi)
    {
        itemFromDb.UpdatedDate = DateTime.Now;

        itemFromDb.Description = itemFromUi.Description;

        itemFromDb.StatusId = itemFromUi.StatusId;

        itemFromDb.Name = itemFromUi.Name;

        itemFromDb.NumericTraffic = itemFromUi.NumericTraffic;

        itemFromDb.PercentageTraffic = itemFromUi.PercentageTraffic;

        itemFromDb.Type = itemFromUi.NumericTraffic;


        itemFromDb.MamConfigurationToBrowser_V1.Clear();



        for (int i = 0; i < itemFromUi.MamConfigurationToBrowser_V1.Count; i++)
        {
            var elementToAdd = itemFromUi.MamConfigurationToBrowser_V1.ElementAt(i);

            elementToAdd.Browser = mMaMDBEntities.Browsers.Single(browserItem => browserItem.BrowserID == elementToAdd.BrowserID);

            elementToAdd.MamConfiguration_V1 = itemFromDb;

            itemFromDb.MamConfigurationToBrowser_V1.Add(elementToAdd);
        }

}

I get the following DB runtime error:

The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.

But that's weird. All the references are not null:

enter image description here

enter image description here

Upadte 2:

I have tried this code:

        try
        {
            item.ThrowIfNull("item");

            var itemFromDB = GetById(item.ConfigurationId);

            if (itemFromDB != null)
            {
                UpdateEfItem(itemFromDB, item);

                //mMaMDBEntities.MamConfiguration_V1.Detach(itemFromDB);

                //mMaMDBEntities.MamConfiguration_V1.Attach(item);

                //mMaMDBEntities.ObjectStateManager.ChangeObjectState(item, System.Data.EntityState.Modified);

                //mMaMDBEntities.ObjectStateManager.ChangeObjectState(itemFromDB, System.Data.EntityState.Modified);


                mMaMDBEntities.SaveChanges();

                return item;
            }

}

        private void UpdateEfItem(MamConfiguration_V1 itemFromDb, MamConfiguration_V1 itemFromUi)
        {
            itemFromDb.UpdatedDate = DateTime.Now;
            itemFromDb.Description = itemFromUi.Description;
            itemFromDb.StatusId = itemFromUi.StatusId;
            itemFromDb.Name = itemFromUi.Name;
            itemFromDb.NumericTraffic = itemFromUi.NumericTraffic;
            itemFromDb.PercentageTraffic = itemFromUi.PercentageTraffic;
            itemFromDb.Type = itemFromUi.NumericTraffic;

            foreach (var item in itemFromDb.MamConfigurationToBrowser_V1.ToList())
            {
                if (itemFromUi.MamConfigurationToBrowser_V1.All(b => b.BrowserVersionId != item.BrowserVersionId))
                {
                    mMaMDBEntities.MamConfigurationToBrowser_V1.DeleteObject(item);
                }
            }

            for (int i = 0; i < itemFromUi.MamConfigurationToBrowser_V1.Count; i++)
            {
                var element = itemFromUi.MamConfigurationToBrowser_V1.ElementAt(i);
                var item = itemFromDb.MamConfigurationToBrowser_V1.SingleOrDefault(b => b.BrowserVersionId == element.BrowserVersionId);
                if (item != null)
                {
                    // copy properties from element to item
                }
                else
                {
                    element.Browser = mMaMDBEntities.Browsers.Single(browserItem =>
                        browserItem.BrowserID == element.BrowserID);

                    element.MamConfiguration_V1 = itemFromDb;

                    //have also tried: element.MamConfiguration_V1 = null;

                    //element.MamConfiguration_V1Reference = null;

                    itemFromDb.MamConfigurationToBrowser_V1.Add(element);
                }
            }
        }

and go this error:

{"Violation of UNIQUE KEY constraint 'UQ_MamConfigurations_V1'. Cannot insert duplicate key in object 'dbo.MamConfiguration_V1'. The duplicate key value is (elad_14Apr_1315).\r\nThe statement has been terminated."}

Upvotes: 1

Views: 3140

Answers (1)

Slauma
Slauma

Reputation: 177133

This line...

itemFromDb.MamConfigurationToBrowser_V1.Clear();

...will not only clear the collection but also set the reference from the individual items in the collection to the parent itemFromDb to null. That's a modification of those items and EF will try to save them to the database. It fails because (probably) the reference is required and cannot be null.

You must take a different approach, that is updating the items in the collection one by one. You must take into account that items could have been deleted in the UI, that they could have been modified and that new items could have been added. It would look similar to this:

private void UpdateEfItem(MamConfiguration_V1 itemFromDb,
    MamConfiguration_V1 itemFromUi)
{
    itemFromDb.UpdatedDate = DateTime.Now;
    itemFromDb.Description = itemFromUi.Description;
    itemFromDb.StatusId = itemFromUi.StatusId;
    itemFromDb.Name = itemFromUi.Name;
    itemFromDb.NumericTraffic = itemFromUi.NumericTraffic;
    itemFromDb.PercentageTraffic = itemFromUi.PercentageTraffic;
    itemFromDb.Type = itemFromUi.NumericTraffic;

    foreach (var item in itemFromDb.MamConfigurationToBrowser_V1.ToList())
    {
        if (!itemFromUi.MamConfigurationToBrowser_V1.Any(b =>
            b.BrowserID == item.BrowserID)
        {
            mMaMDBEntities.Browsers.DeleteObject(item);
        }
    }

    for (int i = 0; i < itemFromUi.MamConfigurationToBrowser_V1.Count; i++)
    {
        var element = itemFromUi.MamConfigurationToBrowser_V1.ElementAt(i);
        var item = itemFromDb.MamConfigurationToBrowser_V1
            .SingleOrDefault(b => b.BrowserID == element.BrowserID);
        if (item != null)
        {
            // copy properties from element to item
        }
        else
        {
            element.Browser = mMaMDBEntities.Browsers.Single(browserItem =>
                browserItem.BrowserID == element.BrowserID);

            itemFromDb.MamConfigurationToBrowser_V1.Add(element);
        }
    }
}

Upvotes: 3

Related Questions