0

I had posted a question here yesterday with plenty of detail Database only updates after closing and opening dialog

In summary, when my child form was closed, my form with the DataGridView was supposed to reload and retrieve the latest data from the database. However, it was retrieving the PRE-Updated data instead of the POST-Updated data.

I discovered that if I changed the way I used the dbcontext when I called my GetAllByTaskId function, it will retrieve the latest data from the database. However, it seems like this only works for certain functions.

For example I have a Delete function that calls a Get function in the same class. If my Get class uses the using() dbcontext method, my delete class will not work. I believe it is because the using() method disposes of the dbcontext and so nothing is carried over to my Delete function.

How would I properly use this using() function in my case? It seems like I would need 2 methods. Also, its strange that my dbcontext wouldn't return the latest data from the database.

private AutoPrintDbContext dbContext = new AutoPrintDbContext();

public FieldsData()
{

}

public List<Field> GetAllByTaskId(string Input)
{
    List<Field> data = new List<Field>();
    try
    {
        using(AutoPrintDbContext db = new AutoPrintDbContext())
        {
            data = db.Fields.Where(x => x.TaskItemId == Input).ToList();
        }
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
    }
    return data;
}

public Field Get(string Input)
{
    Field data = new Field();
    try
    {
        data = dbContext.Fields.SingleOrDefault(u => u.Id == Input);
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
    }
    return data;
}

public bool Delete(string Input)
{
    try
    {
        var f = Get(Input);
        dbContext.Fields.Remove(f);
        dbContext.SaveChanges();
        return true;
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
        return false;
    }
}

This is a windows form app by the way.

8
  • 1
    Don’t catch exceptions unless going to “handle them usefully” - this is C#, not Java :} Randomly empty collections is not overwhelming useful and may hide serious issues. Commented Feb 27, 2019 at 0:42
  • Sorry when you say handle them usefully what do you mean? Also, what do you mean about the random empty collections? Commented Feb 27, 2019 at 0:45
  • 2
    using should be used whenever there is a database operation is happening. this would make sure to open the connection when required and close it as soon as the purpose of opening it is served. For get and delete, you should do get and delete in one single DbContext object created using single using block. So instead of calling Get method separately you should retrieve the data in the delete method itself and delete them and call SaveChanges immediately. In short you dont need class level instance of AutoPrintDbContext. Commented Feb 27, 2019 at 0:48
  • I see. Wouldn't that be doing extra work each time though? I thought that reusing classes was more efficient and that each function should have a single purpose. Sorry I just want to clarify it as I'm still quite new to c# Commented Feb 27, 2019 at 0:50
  • When it comes to database operations it is recommended not to keep the connection open if it is not in use. This would make sure that the connection pool does not run out of connection. Commented Feb 27, 2019 at 0:54

1 Answer 1

1

It seems you need some guidance on how to make proper use of the Entity Framework.

I understand that it may seem counterintuitive that you are creating an instance of DbContext every time you perform an operation (or many inside the using scope) against the DbContext, but the DbContext class as of EF6 is designed with that in mind (see here), otherwise, its change tracking system (which is on by default) will get polluted more and more as you work with a long living instance of it, which will degrade performance overtime, and also depending on what API you use to retrieve an entity (e.g. DbSet.Find()), it will give you back the tracked (cached) instance, instead of pulling it from the database.

Below you can find your example with some modifications for a better way of accomplishing what you need:


public List<Field> GetAllByTaskId(string Input)
{
    using (var db = new AutoPrintDbContext())
    {
        return db.Fields.Where(x => x.TaskItemId == Input).ToList();
    }
}

public Field Get(string Input)
{
    using (var db = new AutoPrintDbContext())
    {
        return db.Fields.SingleOrDefault(u => u.Id == Input);
    }
}

public bool Delete(string Input)
{
    try
    {
        using (var db = new AutoPrintDbContext())
        {
            var f = db.Fields.Single(u => u.Id == Input);
            db.Fields.Remove(f);
            db.SaveChanges();
        }

        return true;
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
        return false;
    }
}

If you want to better understand the Entity Framework, I strongly recommend you to go over the following link: https://learn.microsoft.com/en-us/ef/ef6/fundamentals/performance/perf-whitepaper

Sign up to request clarification or add additional context in comments.

3 Comments

I see. There was a comment that mentioned that I shouldn't use try catch blocks too much as well. I plan on logging the exceptions. Would that be problematic? Thank you for explaining it to me as well.
@JianYA Logging an exception is a perfect use for try/catch blocks
@JianYA, If you want in general log any exceptions during the lifetime of your Winforms application, I recommend you to subscribe to the System.Windows.Forms.Application.ThreadException event in your Program.Main method, just before Application.EnableVisualStyles();; this way you don't have to do a try/catch ceremony everywhere just for that intention. You can find more details about how to use this API here: learn.microsoft.com/en-us/dotnet/api/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.