Search code examples
c#winformsentity-frameworkdispose

UserControl and EF context dispose


I have a UserControl where I am using my EF context to load the data from DB to a dataGridView in order to enable the user to make some changes:

    public partial class MyUserControl: UserControl
    {
        MyEntities context;

        public ViewMasterData()
        {
            InitializeComponent();
            createComboBoxTable();
        }

        private void MyUserControl_Load(object sender, EventArgs e)
        {
            context = new MyEntities();
        }

    // Other methods to fill the dataGridView and Save the data back to the DB

        private void SaveChanges()
        {
            context.SaveChanges();                
        }
    }

I would like to dispose the context when I am leaving the UserControl (i.e. navigate to another UserControl), but it seems that calling context.Dispose() on the Dispose method of the UserControl (in the code-generated) is not working since it is called only when I close the whole WinForm. I cannot use the "using" because I need to keep the context open to perform changes and then save.

The question is: how can I correctly dispose the context when I leaving the UserControl? THANKS!


Solution

  • I believe it is considered bad practice to keep the EF context open. Instead create a new instance of your context whenever you need it.. Indeed, wrapping the context within a using statement will dispose of it automatically via garbage collecion.

    public partial class MyUserControl: UserControl
    {
        // MyEntities context; i dont need this
    
        public ViewMasterData()
        {
            InitializeComponent();
            // createComboBoxTable();
        }
    
        private void MyUserControl_Load(object sender, EventArgs e)
        {
            using (var context = new MyEntitiesContext())
            {
                createComboBoxTable(context.MyEntities.ToList());
            }
        }
    
        private void SaveNewMyEntity(MyEntity newEntity)
        {
            using (var context = new MyEntitiesContext())
            {
                // some logic here to check for uniqueness etc
    
                context.MyEntities.Add(newEntity);
                context.SaveChanges(); 
            }
        }
    
        private void UpdateExistingMyEntity(MyEntity updatedEntity)
        {
            using (var context = new MyEntitiesContext())
            {
                context.Entry(updatedEntity).State = EntityState.Modified;
                context.SaveChanges(); 
            }
        }
    }
    

    UPDATE:

    I agree its better to add multiple entities in one go, all you need is a foreach loop, and perhaps a little bool property indicating if a MyEntity instance has been updated. Something like this is a possible solution:

    private void UpdateExistingMyEntity(IEnumerable<MyEntity> updatedEntities)
    {
        using (var context = new MyEntitiesContext())
        {
            foreach(MyEntity e in updatedEntities)
                context.Entry(e).State = EntityState.Modified;
    
            context.SaveChanges(); 
        }
    }
    

    When the user clicks the Save button ...

    private void saveBtn_Click(object sender, RoutedEventArgs e)
    {
        IEnumerable<MyEntity> updatedEntities = myGridData.Where(o => o.HasBeenUpdated == true);
    
        UpdateExistingMyEntity(updatedEntities);
    
        foreach(MyEntity e in updatedEntities)
            e.HasBeenUpdated = false;
    }