Pergunta

I am beginning a new project and am wanting to leverage off of the async/await items in .NET along with the new Async operations in entity framework (version 6.1). However, what I am curious about is how to refactor certain parts of my application to reduce code repetition and the best way to accomplish this given the non-thread-safe nature of EF.

Example, I have a few methods in my service layer that look something like this

public async Task<MyViewModel> GetProgramIndexAsync(long programId){
            using (var db = new DbEntities())
            {
                var program = await db.Programs.FirstOrDefaultAsync(x => x.Id == programId && x.Active);
                if (program == null)
                {
                    throw new ApplicationException("Cannot find the requested program");
                }
            //more code to populate the view model
            }
        }

So far, so good. But I find myself doing this check in multiple places in this service layer. What would be ideal would be to extract that to a separate function

private async Task<Program> GetProgramAsync(long programId){
            using (var db = new DbEntities())
            {
                var program = await db.Programs.FirstOrDefaultAsync(x => x.Id == programId && x.Active);
                if (program == null)
                {
                    throw new ApplicationException("Cannot find the requested program");
                }
            return program;
            }
        }

Now, my public service layer calls can simply call this function and not have to repeat this check each time.

var program = await GetProgramAsync(programId);

My concern is the spinning up of multiple contexts for each one of these requests. In the past (synchronous), I could simply have a second function parameter such as

private async Task<Program> GetProgramAsync(long programId, DbContext db){

and pass the existing context into the method. However, I am assuming this would be bad with the async/await nature.

Am I over thinking this (multiple contexts are not that bad) or is there a better way of accomplishing this? I should note that these calls are read only and I will not be updating entities in this manner.

Foi útil?

Solução

Neither of the problems you think you have are problems.

  1. Spinning up multiple contexts isn't really a problem, thanks to connection pooling. Creating a new context doesn't actually need to create a new database connection, it just grabs one from the pool. If you're putting one back into the pool right before you're about to need a new one, instead of holding a lot of concurrent connections, this has very little overhead.

  2. If you do pass around contexts between these methods its still not a problem. The code is asynchronous, but it is not doing anything in parallel. The context is only ever used by a single thread at a time. You're always awaiting any operation that would potentially be asynchronous, which means that while other code that is entirely related to these methods may be using the CPU, whether that be another response handler (if this is ASP), the UI pumping other events (if this is a desktop app), or something else, you're still not put in the position of accessing this context from multiple threads at once.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top