Skip to main content
Question Protected by gnat
Bumped by Community user
Bumped by Community user
Bumped by Community user
Tweeted twitter.com/StackSoftEng/status/1149060794430251009
replaced http://stackoverflow.com/ with https://stackoverflow.com/
Source Link

We are working on a large-ish MVC web application with multiple backing stores including a SQL Server database accessed via Entity Framework 6.0. We are using asynchronous operations wherever we can, but we repeatedly--in initial implementations--come across scenarios where we inadvertently start a second async operation on the same EF context (we use the same context for all EF operations), which throws an exception.

I am not new to C# enterprise app development, but I am pretty new to EF and I've been thinking about possible ways to communicate that a given repo method must be awaited immediately instead of potentially included in a Task.WhenAll() or awaited after another method. Has anyone considered this?

Some pseudo-code for discussion purposes:

// we know that our CURRENT implementation of ICarRepo will utilize EF
// this declaration is in a backend-agnostic library
public interface ICarRepo
{
  Task<ICar> GetAsync(int carID);
}

// in our EF project
public class CarRepoEF: ICarRepo
{
   public async Task<ICar> GetAsync(int carID)
   {
     return await DataContext.Cars.SingleOrDefaultAsync(c => c.ID == carID);
   }
}

Our current approach is to simply provide comments in scenarios where we can fire off an async repo method and continue before awaiting the result:

// not EF
var driverTask = driverRepo.GetAsync(driverID);
//...other repo methods, logic, object instantiation, etc
// EF, await it immediately
var car = await carRepo.GetAsync(carID);
var driver = await driverTask;

We are using DI everywhere (including the DataContext in a request scope) so if we wanted to communicate this to consumers we'd have to do so through the backend-agnostic interface, which makes me think this is perhaps a fool's errand (why make the repo interface communicate a limitation of the current implementation of the interface?). Specifically, I was considering wrapping Task in a custom class that would communicate that it can't handle more than one at a time (singleton???), or extending Task itself to communicate the same and have interfaces that front EF operations return these instead of a plain Task.

Should I give up on trying to engineer a solution to this quasi-problem? Is there a more fundamental, architectural change that could make this problem go away that I am not aware of?

EDIT

After some more research, I did find a SO questionquestion that deals with this issue (even using the same DI framework) and one of the answers introduced the idea of using a factory to create contexts.

We are working on a large-ish MVC web application with multiple backing stores including a SQL Server database accessed via Entity Framework 6.0. We are using asynchronous operations wherever we can, but we repeatedly--in initial implementations--come across scenarios where we inadvertently start a second async operation on the same EF context (we use the same context for all EF operations), which throws an exception.

I am not new to C# enterprise app development, but I am pretty new to EF and I've been thinking about possible ways to communicate that a given repo method must be awaited immediately instead of potentially included in a Task.WhenAll() or awaited after another method. Has anyone considered this?

Some pseudo-code for discussion purposes:

// we know that our CURRENT implementation of ICarRepo will utilize EF
// this declaration is in a backend-agnostic library
public interface ICarRepo
{
  Task<ICar> GetAsync(int carID);
}

// in our EF project
public class CarRepoEF: ICarRepo
{
   public async Task<ICar> GetAsync(int carID)
   {
     return await DataContext.Cars.SingleOrDefaultAsync(c => c.ID == carID);
   }
}

Our current approach is to simply provide comments in scenarios where we can fire off an async repo method and continue before awaiting the result:

// not EF
var driverTask = driverRepo.GetAsync(driverID);
//...other repo methods, logic, object instantiation, etc
// EF, await it immediately
var car = await carRepo.GetAsync(carID);
var driver = await driverTask;

We are using DI everywhere (including the DataContext in a request scope) so if we wanted to communicate this to consumers we'd have to do so through the backend-agnostic interface, which makes me think this is perhaps a fool's errand (why make the repo interface communicate a limitation of the current implementation of the interface?). Specifically, I was considering wrapping Task in a custom class that would communicate that it can't handle more than one at a time (singleton???), or extending Task itself to communicate the same and have interfaces that front EF operations return these instead of a plain Task.

Should I give up on trying to engineer a solution to this quasi-problem? Is there a more fundamental, architectural change that could make this problem go away that I am not aware of?

EDIT

After some more research, I did find a SO question that deals with this issue (even using the same DI framework) and one of the answers introduced the idea of using a factory to create contexts.

We are working on a large-ish MVC web application with multiple backing stores including a SQL Server database accessed via Entity Framework 6.0. We are using asynchronous operations wherever we can, but we repeatedly--in initial implementations--come across scenarios where we inadvertently start a second async operation on the same EF context (we use the same context for all EF operations), which throws an exception.

I am not new to C# enterprise app development, but I am pretty new to EF and I've been thinking about possible ways to communicate that a given repo method must be awaited immediately instead of potentially included in a Task.WhenAll() or awaited after another method. Has anyone considered this?

Some pseudo-code for discussion purposes:

// we know that our CURRENT implementation of ICarRepo will utilize EF
// this declaration is in a backend-agnostic library
public interface ICarRepo
{
  Task<ICar> GetAsync(int carID);
}

// in our EF project
public class CarRepoEF: ICarRepo
{
   public async Task<ICar> GetAsync(int carID)
   {
     return await DataContext.Cars.SingleOrDefaultAsync(c => c.ID == carID);
   }
}

Our current approach is to simply provide comments in scenarios where we can fire off an async repo method and continue before awaiting the result:

// not EF
var driverTask = driverRepo.GetAsync(driverID);
//...other repo methods, logic, object instantiation, etc
// EF, await it immediately
var car = await carRepo.GetAsync(carID);
var driver = await driverTask;

We are using DI everywhere (including the DataContext in a request scope) so if we wanted to communicate this to consumers we'd have to do so through the backend-agnostic interface, which makes me think this is perhaps a fool's errand (why make the repo interface communicate a limitation of the current implementation of the interface?). Specifically, I was considering wrapping Task in a custom class that would communicate that it can't handle more than one at a time (singleton???), or extending Task itself to communicate the same and have interfaces that front EF operations return these instead of a plain Task.

Should I give up on trying to engineer a solution to this quasi-problem? Is there a more fundamental, architectural change that could make this problem go away that I am not aware of?

EDIT

After some more research, I did find a SO question that deals with this issue (even using the same DI framework) and one of the answers introduced the idea of using a factory to create contexts.

Added link to SO question dealing with this issue
Source Link

We are working on a large-ish MVC web application with multiple backing stores including a SQL Server database accessed via Entity Framework 6.0. We are using asynchronous operations wherever we can, but we repeatedly--in initial implementations--come across scenarios where we inadvertently start a second async operation on the same EF context (we use the same context for all EF operations), which throws an exception.

I am not new to C# enterprise app development, but I am pretty new to EF and I've been thinking about possible ways to communicate that a given repo method must be awaited immediately instead of potentially included in a Task.WhenAll() or awaited after another method. Has anyone considered this?

Some pseudo-code for discussion purposes:

// we know that our CURRENT implementation of ICarRepo will utilize EF
// this declaration is in a backend-agnostic library
public interface ICarRepo
{
  Task<ICar> GetAsync(int carID);
}

// in our EF project
public class CarRepoEF: ICarRepo
{
   public async Task<ICar> GetAsync(int carID)
   {
     return await DataContext.Cars.SingleOrDefaultAsync(c => c.ID == carID);
   }
}

Our current approach is to simply provide comments in scenarios where we can fire off an async repo method and continue before awaiting the result:

// not EF
var driverTask = driverRepo.GetAsync(driverID);
//...other repo methods, logic, object instantiation, etc
// EF, await it immediately
var car = await carRepo.GetAsync(carID);
var driver = await driverTask;

We are using DI everywhere (including the DataContext in a request scope) so if we wanted to communicate this to consumers we'd have to do so through the backend-agnostic interface, which makes me think this is perhaps a fool's errand (why make the repo interface communicate a limitation of the current implementation of the interface?). Specifically, I was considering wrapping Task in a custom class that would communicate that it can't handle more than one at a time (singleton???), or extending Task itself to communicate the same and have interfaces that front EF operations return these instead of a plain Task.

Should I give up on trying to engineer a solution to this quasi-problem? Is there a more fundamental, architectural change that could make this problem go away that I am not aware of?

EDIT

After some more research, I did find a SO question that deals with this issue (even using the same DI framework) and one of the answers introduced the idea of using a factory to create contexts.

We are working on a large-ish MVC web application with multiple backing stores including a SQL Server database accessed via Entity Framework 6.0. We are using asynchronous operations wherever we can, but we repeatedly--in initial implementations--come across scenarios where we inadvertently start a second async operation on the same EF context (we use the same context for all EF operations), which throws an exception.

I am not new to C# enterprise app development, but I am pretty new to EF and I've been thinking about possible ways to communicate that a given repo method must be awaited immediately instead of potentially included in a Task.WhenAll() or awaited after another method. Has anyone considered this?

Some pseudo-code for discussion purposes:

// we know that our CURRENT implementation of ICarRepo will utilize EF
// this declaration is in a backend-agnostic library
public interface ICarRepo
{
  Task<ICar> GetAsync(int carID);
}

// in our EF project
public class CarRepoEF: ICarRepo
{
   public async Task<ICar> GetAsync(int carID)
   {
     return await DataContext.Cars.SingleOrDefaultAsync(c => c.ID == carID);
   }
}

Our current approach is to simply provide comments in scenarios where we can fire off an async repo method and continue before awaiting the result:

// not EF
var driverTask = driverRepo.GetAsync(driverID);
//...other repo methods, logic, object instantiation, etc
// EF, await it immediately
var car = await carRepo.GetAsync(carID);
var driver = await driverTask;

We are using DI everywhere (including the DataContext in a request scope) so if we wanted to communicate this to consumers we'd have to do so through the backend-agnostic interface, which makes me think this is perhaps a fool's errand (why make the repo interface communicate a limitation of the current implementation of the interface?). Specifically, I was considering wrapping Task in a custom class that would communicate that it can't handle more than one at a time (singleton???), or extending Task itself to communicate the same and have interfaces that front EF operations return these instead of a plain Task.

Should I give up on trying to engineer a solution to this quasi-problem? Is there a more fundamental, architectural change that could make this problem go away that I am not aware of?

We are working on a large-ish MVC web application with multiple backing stores including a SQL Server database accessed via Entity Framework 6.0. We are using asynchronous operations wherever we can, but we repeatedly--in initial implementations--come across scenarios where we inadvertently start a second async operation on the same EF context (we use the same context for all EF operations), which throws an exception.

I am not new to C# enterprise app development, but I am pretty new to EF and I've been thinking about possible ways to communicate that a given repo method must be awaited immediately instead of potentially included in a Task.WhenAll() or awaited after another method. Has anyone considered this?

Some pseudo-code for discussion purposes:

// we know that our CURRENT implementation of ICarRepo will utilize EF
// this declaration is in a backend-agnostic library
public interface ICarRepo
{
  Task<ICar> GetAsync(int carID);
}

// in our EF project
public class CarRepoEF: ICarRepo
{
   public async Task<ICar> GetAsync(int carID)
   {
     return await DataContext.Cars.SingleOrDefaultAsync(c => c.ID == carID);
   }
}

Our current approach is to simply provide comments in scenarios where we can fire off an async repo method and continue before awaiting the result:

// not EF
var driverTask = driverRepo.GetAsync(driverID);
//...other repo methods, logic, object instantiation, etc
// EF, await it immediately
var car = await carRepo.GetAsync(carID);
var driver = await driverTask;

We are using DI everywhere (including the DataContext in a request scope) so if we wanted to communicate this to consumers we'd have to do so through the backend-agnostic interface, which makes me think this is perhaps a fool's errand (why make the repo interface communicate a limitation of the current implementation of the interface?). Specifically, I was considering wrapping Task in a custom class that would communicate that it can't handle more than one at a time (singleton???), or extending Task itself to communicate the same and have interfaces that front EF operations return these instead of a plain Task.

Should I give up on trying to engineer a solution to this quasi-problem? Is there a more fundamental, architectural change that could make this problem go away that I am not aware of?

EDIT

After some more research, I did find a SO question that deals with this issue (even using the same DI framework) and one of the answers introduced the idea of using a factory to create contexts.

Source Link

Enforce No Multiple Async Entity Framework Operations

We are working on a large-ish MVC web application with multiple backing stores including a SQL Server database accessed via Entity Framework 6.0. We are using asynchronous operations wherever we can, but we repeatedly--in initial implementations--come across scenarios where we inadvertently start a second async operation on the same EF context (we use the same context for all EF operations), which throws an exception.

I am not new to C# enterprise app development, but I am pretty new to EF and I've been thinking about possible ways to communicate that a given repo method must be awaited immediately instead of potentially included in a Task.WhenAll() or awaited after another method. Has anyone considered this?

Some pseudo-code for discussion purposes:

// we know that our CURRENT implementation of ICarRepo will utilize EF
// this declaration is in a backend-agnostic library
public interface ICarRepo
{
  Task<ICar> GetAsync(int carID);
}

// in our EF project
public class CarRepoEF: ICarRepo
{
   public async Task<ICar> GetAsync(int carID)
   {
     return await DataContext.Cars.SingleOrDefaultAsync(c => c.ID == carID);
   }
}

Our current approach is to simply provide comments in scenarios where we can fire off an async repo method and continue before awaiting the result:

// not EF
var driverTask = driverRepo.GetAsync(driverID);
//...other repo methods, logic, object instantiation, etc
// EF, await it immediately
var car = await carRepo.GetAsync(carID);
var driver = await driverTask;

We are using DI everywhere (including the DataContext in a request scope) so if we wanted to communicate this to consumers we'd have to do so through the backend-agnostic interface, which makes me think this is perhaps a fool's errand (why make the repo interface communicate a limitation of the current implementation of the interface?). Specifically, I was considering wrapping Task in a custom class that would communicate that it can't handle more than one at a time (singleton???), or extending Task itself to communicate the same and have interfaces that front EF operations return these instead of a plain Task.

Should I give up on trying to engineer a solution to this quasi-problem? Is there a more fundamental, architectural change that could make this problem go away that I am not aware of?