tyrion
tyrion

Reputation: 742

Use of using statement for Entity Framework DbContext in foreach-loop

There is a parser that parses a text file which contains object definition. The object definitions in the text file have a placeholder handle key. The place holder handle needs to be replaced with actual value by looking up the handle value in DB. In my application I am making use of the Entity framework Core for working with the DB.

The parser returns one object at a time, and I am looking up the handle and other properties in the DB one at a time. This is how the code looks so far:

    IEnumerable<ObjectInfo> GetNextContent();

    IEnumerable<ObjectInfo> GetNextObjectInfo()
    {

        foreach (var item in parser.GetNextContent())
        {
            using (var dbContext = new ContentDbContext())
            {
                string key = item.Key;

                string id = dbContext.Contents.Find(key).ObjectId;
                item.Id = id;
                // Assign other fields...

                yield return item;
            }
        }
    }

The question that I have is that in the code above, the 'using' block is within the foreach loop. Is this a right thing to do? The other thought is that I can take the 'using' block outside of the foreach-loop but then I am not sure how would that play out with the iterator in the code.

Upvotes: 2

Views: 3084

Answers (1)

Nguyễn Văn Phong
Nguyễn Văn Phong

Reputation: 14218

You should move ContentDbContext into outside for better performance.

This is simply because You just need one context per request.

One DbContext per web request... why?

using (var dbContext = new ContentDbContext())
 {
    foreach (var item in parser.GetNextContent())
     {
            string key = item.Key;

            string id = dbContext.Contents.Find(key).ObjectId;
            item.Id = id;
            // Assign other fields...

            yield return item;
        }
    }

Updated

You might also join then make sure that fetch all data at a time

// You need to fetch all `item.Key` from `parser.GetNextContent()` to get all data in `dbContext.Contents`
var keys = parser.GetNextContent().Select(p => p.Key).ToArray();

var result = (from content in dbContext.Contents 
              join key in keys on content.Id equals key 
              select new 
{
  Id = content.ObjectId,
  //....
}  

If you are use C# 8, using statement may be as below:

 using var dbContext = new ContentDbContext();

 foreach (var item in parser.GetNextContent())
 {
        string key = item.Key;

        string id = dbContext.Contents.Find(key).ObjectId;
        item.Id = id;
        // Assign other fields...

        yield return item;
  }

Upvotes: 3

Related Questions