0
votes

I'm having an issue where Entity Framework isn't persisting changes to the DB. I use a static method to load up some values and the Entity context is thrown away (in a using statement).

The objects are then loaded into a WPF DataGrid where they can be manipulated by the end user.

When the user is finished making changes an "update" button is pressed and the list of objects is sent back to the data layer to be persisted to the DB. I can see objects that were changed in the UI reflect their new value (ie not a data binding issue).

I would assume since the entity context that loaded the objects has since been disposed of I should then attach these objects to be persisted to the newly created context. Correct? When I do this the entity state of the modified object (I can see that is what the state is set to) changes to "Unchanged". Nothing is persisted to the DB.

What the heck am I missing?!

Here is the code to load and update the values:

public static List<SSIS_Configuration> GetConfigurationValuesForTenant(string tenantKey, SqlConnectionString connectionString)
    {
        List<SSIS_Configuration> configStrings = new List<SSIS_Configuration>();
        if (connectionString.IsValid())
        {
            try
            {

                using (SSISFrameworkEntities entities = new SSISFrameworkEntities(connectionString.ToEDMXString("SSISFramework.SSISFramework")))
                {
                    string configFilterStartingValue = "CommonConfig_" + tenantKey;

                    configStrings = (from configString in entities.SSIS_Configurations
                                    where configString.ConfigurationFilter.StartsWith(configFilterStartingValue)
                                    select configString).ToList();
                }
            }
            catch { }
        }

        return configStrings;
    }

    public static void UpdateConfigurations(List<SSIS_Configuration> configurations, SqlConnectionString connectionString)
    {
        if (connectionString.IsValid())
        {
            try
            {
                using (SSISFrameworkEntities entities = new SSISFrameworkEntities(connectionString.ToEDMXString("SSISFramework.SSISFramework")))
                {
                    foreach (SSIS_Configuration config in configurations)
                    {
                        entities.Attach(config);
                    }

                    entities.SaveChanges();
                }
            }
            catch { }
        }
    }
1
Try keeping the context in a place like App.Current.Properties["context"]. Unless they are self tracking entities, the changes won't be noticed when using a new context even if you attach. - Dustin Davis
My preference is to hold my context inside an IoC container such as Unity. Then I can set parameters to control the lifecycle. You can then use contructor injection to make sure all your viewmodels have access to the context object. - Winger
@Dustin, I don't know if that will be appropriate for my solution as this code is stored in a class library to be used by different end UI solutions. While the main use will be with a Windows WPF client it will most likely be used by a console app and perhaps a Silverlight app. When is App.Current available? - Mike G
@Mike G the point is, when you destroy the context you lose tracking. Use self tracking entities or don't destroy the context. - Dustin Davis
@Winger, my thought was to build a static "Runtime" class, but I don't have a need for it other than this holder. I've typically built these static classes before, but wanted to keep the number of utility classes down in this solution. If I can't get any other good solutions I may have to revert to that design. I had thought I could treat the entity context as I did with "requests" in a web app. I would build a new context for each request and then dispose of it at the end of the request. I thought this would do the same. - Mike G

1 Answers

1
votes

WPF application is scenario for attached entities so you should not dispose context if you are going to change entities loaded from the context. If you dispose it you must implement a lot of additional logic because you must tell a new context about every single change a user did to the entities and relations.

So in your scenario calling Attach will only connects entities to the context but you need to set also their state (attaching put entities into Unchanged state). Be aware that you must set state correctly to Modified, Deleted or Inserted based on the operation you want to perform. If your changed entities have some relations which have been also changes you must set state for related entities as well and in case of changed relation between entities you must change state of relations itself as well.