Configuring EF to throw if accessing navigation property not eager loaded (and lazy-load is disabled) - entity-framework

We have a few apps that are currently using an EF model that has lazy-loading enabled. When I turn off the lazy-loading (to avoid implicit loads and most of our N+1 selects), I'd much rather have accessing a should-have-been-eager-loaded (or manually Load() on the reference) throw an exception instead of returning null (since a specific exception for this would be nicer and easier to debug than a null ref).
I'm currently leaning towards just modifying the t4 template to do so (so, if reference.IsLoaded == false, throw), but wondered if this was already a solved problem, either in the box or via another project.
Bonus points for any references to plugins/extensions/etc that can do source analysis and detect such problems. :)

I wanted to do the same thing (throw on lazy loading) for several performance-related reasons - I wanted to avoid sync queries because they block the thread, and in some places I want to avoid loading a full entity and instead just load the properties that the code needs.
Just disabling lazy loading isn't good enough because some entities have properties that can legitimately be null, and I don't want to confuse "null because it's null" with "null because we decided not to load it".
I also wanted to only optionally throw on lazy loading in some specific code paths where I know lazy loading is problematic.
Below is my solution.
In my DbContext class, add this property:
class AnimalContext : DbContext
{
public bool ThrowOnSyncQuery { get; set; }
}
Somewhere in my code's startup, run this:
// Optionally don't let EF execute sync queries
DbInterception.Add(new ThrowOnSyncQueryInterceptor());
The code for ThrowOnSyncQueryInterceptor is as follows:
public class ThrowOnSyncQueryInterceptor : IDbCommandInterceptor
{
public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
OptionallyThrowOnSyncQuery(interceptionContext);
}
public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
}
public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
OptionallyThrowOnSyncQuery(interceptionContext);
}
public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
}
public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
OptionallyThrowOnSyncQuery(interceptionContext);
}
public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
}
private void OptionallyThrowOnSyncQuery<T>(DbCommandInterceptionContext<T> interceptionContext)
{
// Short-cut return on async queries.
if (interceptionContext.IsAsync)
{
return;
}
// Throw if ThrowOnSyncQuery is enabled
AnimalContext context = interceptionContext.DbContexts.OfType<AnimalContext>().SingleOrDefault();
if (context != null && context.ThrowOnSyncQuery)
{
throw new InvalidOperationException("Sync query is disallowed in this context.");
}
}
}
Then in the code that uses AnimalContext
using (AnimalContext context = new AnimalContext(_connectionString))
{
// Disable lazy loading and sync queries in this code path
context.ThrowOnSyncQuery = true;
// Async queries still work fine
var dogs = await context.Dogs.Where(d => d.Breed == "Corgi").ToListAsync();
// ... blah blah business logic ...
}

jamesmanning, the creator of the project https://github.com/jamesmanning/EntityFramework.LazyLoadLoggingInterceptor, managed to intercept lazy-loaded calls by reading the stack trace.
So in you could create DbCommandInterceptor that does something like:
public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
// unfortunately not a better way to detect whether the load is lazy or explicit via interceptor
var stackFrames = new StackTrace(true).GetFrames();
var stackMethods = stackFrames?.Select(x => x.GetMethod()).ToList();
var dynamicProxyPropertyGetterMethod = stackMethods?
.FirstOrDefault(x =>
x.DeclaringType?.FullName.StartsWith("System.Data.Entity.DynamicProxies") == true &&
x.Name.StartsWith("get_"));
if (dynamicProxyPropertyGetterMethod != null)
{
throw new LazyLoadingDisallowedException();
}
I know that reading the stack trace frames can be expensive, although my guess would be that in normal circumstances where data access is occurring, the cost is negligible compared to the data access itself. However you will want to assess the performance of this method for yourself.
(As a side note, what you are after is one of the many nice features that NHibernate has had for many many years).

You shouldn't have to modify the T4. Based on mention of "T4" I'm guessing you are using EDMX. The properties window of the container has the lazyloadingenabled property. It's set to true when you create a new model. You can change it to false. T4 template will see that and add the code into the ctor.
Also if you're using Microsoft's POCO templates, they'll add the virtual keyword to your nav properties. Virtual + lazyloadingenabled is the necessary combination to get lazy loading. If you remove the virtual keyword then the property will never be lazy loaded, eve if lazyloading is enabled.
hth
julie

Related

How Do I Create a DbContextFactory Within a Blazor Background Service?

I am working on my first Blazor Server application, which is also my first Entity Framework Core application. I am wanting to set up a background service which, once a day in the early morning, checks the database to see if any of a certain record type has been added with yesterday's date. If so, the relevant records are pulled, formatted, and then emailed to a stakeholder.
I have the EF, formatting, and emailing code working just fine when I trigger the report by manually visiting the page. The problem that I have is how to provide the background service with a DbContextFactory so that the EF and related code can execute.
Up to this point I've always used Razor-based dependency injection to inject the IDbContextFactory via an inject IDbContextFactory<OurAppContext> DbFactory at the top of the page, and then accessed the DbFactory via the DbFactory variable.
However, background services are (according to this Microsoft tutorial) set up through Program.cs, so I don't have access to Razor-based dependency injection there.
I have set up my background service (what I call the PhaseChangeReportService) as indicated in the above link, and it dutifully outputs to the console every 10 seconds that it is running with an updated execution count. I don't fully understand what's going on with the various layers of indirection, but it appears to be working as Microsoft intended.
I noted that the constructor for the background service takes in an ILogger as a parameter, specifically:
namespace miniDARTS.ScopedService
{
public sealed class PhaseChangeReportService : IScopedProcessingService
{
private int _executionCount;
private readonly ILogger<PhaseChangeReportService> _logger;
public PhaseChangeReportService(ILogger<PhaseChangeReportService> logger)
{
_logger = logger;
}
public async Task DoWorkAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
++_executionCount;
_logger.LogInformation("{ServiceName} working, execution count: {Count}", nameof(PhaseChangeReportService), _executionCount);
await Task.Delay(10_000, stoppingToken);
}
}
}
}
I was (and am) confused that the constructor is never referenced within Visual Studio, but when I drop a breakpoint on its one line of code it is hit. I tried modifying this constructor's signature so that it took in an IDbFactory<OurAppContext> as well, so that whatever dark magic is allowing an ILogger<BackgroundServiceType> to come in for assignment to _logger might bring in a DbFactory<OurAppContext> as well, like so:
private readonly ILogger<PhaseChangeReportService> _logger;
private readonly IDbContextFactory<miniDARTSContext> _dbContextFactory;
public PhaseChangeReportService(ILogger<PhaseChangeReportService> logger, IDbContextFactory<miniDARTSContext> dbContextFactory)
{
_logger = logger;
_dbContextFactory = dbContextFactory;
}
However, doing so just led to the constructor breakpoint being skipped over and not breaking, with no exception being thrown or any console output of any kind (i.e. the prior execution count console output no longer showed up). So, I gave up on that approach.
Here is the relevant section of Program.cs:
// Configure the database connection.
string connectionString = builder.Configuration.GetConnectionString("miniDARTSContext");
var serverVersion = new MySqlServerVersion(new Version(8, 0, 28));
builder.Services.AddDbContextFactory<miniDARTSContext>(options => options.UseMySql(connectionString, serverVersion), ServiceLifetime.Scoped);
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<ScopedBackgroundService>();
services.AddScoped<IScopedProcessingService, PhaseChangeReportService>();
})
.Build();
host.RunAsync();
Here's IScopedProcessingService.cs:
namespace miniDARTS.ScopedService
{
public interface IScopedProcessingService
{
Task DoWorkAsync(CancellationToken stoppingToken);
}
}
And here's ScopedBackgroundService.cs:
namespace miniDARTS.ScopedService;
public sealed class ScopedBackgroundService : BackgroundService
{
private readonly IServiceProvider _serviceProvider;
private readonly ILogger<ScopedBackgroundService> _logger;
public ScopedBackgroundService(IServiceProvider serviceProvider, ILogger<ScopedBackgroundService> logger)
{
_serviceProvider = serviceProvider;
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation($"{nameof(ScopedBackgroundService)} is running.");
await DoWorkAsync(stoppingToken);
}
private async Task DoWorkAsync(CancellationToken stoppingToken)
{
_logger.LogInformation($"{nameof(ScopedBackgroundService)} is working.");
using (IServiceScope scope = _serviceProvider.CreateScope())
{
IScopedProcessingService scopedProcessingService = scope.ServiceProvider.GetRequiredService<IScopedProcessingService>();
await scopedProcessingService.DoWorkAsync(stoppingToken);
}
}
public override async Task StopAsync(CancellationToken stoppingToken)
{
_logger.LogInformation($"{nameof(ScopedBackgroundService)} is stopping.");
await base.StopAsync(stoppingToken);
}
}
I'm confident I'm misunderstanding something relatively fundamental here when it comes to services / dependency injection, but my Googling and review of past StackOverflow answers has not turned up anything I can run with.
The IDbContextFactory is an interface that is used for creating instances of a DbContext. When you add it to your services on program.cs for Blazor (services.AddDbContextFactory(parameters)), it implements the IDbContextFactory for you. This allows you to use the #inject IDbContextFactory<YourDbContext> DbFactory at the top of your razor components and then within your code you can call the CreateDbContext method when you need to create an instance of the DbContext (ex. using var context = DbFactory.CreateDbContext()).
You can pass an injected DbContextFactory as a parameter from a razor component to a class, and then use that DbContextFactory in a method to create an instance of the DbContext (see constructor injection), but that still relies on the razor component to inject the DbContextFactory to begin with.
To create an instance of a DbContext independent of a razor component, you need to use the constructor for your DbContext. Your DbContext will have a public constructor with a DbContextOptions parameter (this is required to be able to use AddDbContextFactory when registering the factory service in program.cs). You can use this constructor to implement your own factory. If you aren't sure which options to use, you can check your program.cs to see what options you used there.
public class YourDbFactory : IDbContextFactory<YourDbContext>
{
public YourDbContext CreateDbContext()
{
var optionsBuilder = new DbContextOptionsBuilder<YourDbContext>();
optionsBuilder.UseSqlServer(#"Server=(localdb)\mssqllocaldb;Database=Test"));
return new YourDbContext(optionsBuilder);
}
}
Once you've created your own implementation of the IDbContextFactory interface, you can then use it in your code independent of razor components - for example in the background service class.
YourDbFactory DbFactory = new YourDbFactory();
using var context = DbFactory.CreateDbContext();

Get generated SQL for a DbContext.SaveChanges in Entity Framework Core

In Entity Framework Core, is it possible to see the SQL that will be applied when the SaveChanges() method is called on the DbContext?
EF Core 5.0+
There are a simple builtin solution, add the following function to the DbContext class.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.LogTo(Console.WriteLine);
this will log both queries and commands.
See here for mote details: Simple Logging
Here are the docs on creating a LoggerFactory in Core 3. In short:
var loggerFactory = LoggerFactory.Create(builder =>
{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole()
.AddEventLog();
});
You may need to add a reference to Microsoft.Extensions.Logging.Console.
Use the DbContextOptionsBuilder to enable logging for a context.
optionsBuilder.UseLoggerFactory(loggerFactory)
I'll repeat the warning from here:
It is very important that applications do not create a new ILoggerFactory instance for each context instance. Doing so will result in a memory leak and poor performance.
Therefore, they recommend using a singleton/global instance:
public static readonly ILoggerFactory MyLoggerFactory =
LoggerFactory.Create(builder => { builder.AddConsole(); });
you can use console logger "EF Core logging automatically integrates with the logging mechanisms of .NET Core "
you can read about here :
https://www.entityframeworktutorial.net/efcore/logging-in-entityframework-core.aspx
You can use DbContextOptionsBuilder.UseLoggerFactory(loggerFactory) method to log all sql output.By using constructor Injection like below
public class DemoContext : ObjContext
{
private readonly ILoggerFactory _loggerFactory;
public DemoContext() { }
public DemoContext(ILoggerFactory loggerFactory)
{
_loggerFactory = loggerFactory;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder.UseLoggerFactory(_loggerFactory);
}
}
using (var context = new DemoContext(_loggerFactory))
{
var Employees = context.Employee.ToList();
}
Or
I suggest a few other ways of viewing the SQL generated is to use reflection to create an ObjectQuery object and then call the ToTraceString() method to actually store the query results.
using (var context = new EntityContext())
{
var query = context.Customers.Where(c => c.Id == 1);
var sql = ((System.Data.Objects.ObjectQuery)query).ToTraceString();
}
Use SQL Logging
Using The DbContext.Database.Log property can be set to a delegate for any method that takes a string.
Log SQL to the Console.
using (var context = new EntityContext())
{
context.Database.Log = Console.Write;
}
Log SQL to Visual Studio Output panel.
using (var context = new EntityContext())
{
context.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
}
It's a bit tricky to log EF Core's SQL in an ASP.NET MVC web app. Unlike Entity Framework, EF Core lacks the easy-to-use DBContext.Database.Log property. As #DharmaTurtle mentioned, you can use LoggerFactory.Create, and this can work, but it does create a separate ILoggerFactory than the one that the rest of the app uses for logging (one that is apparently not using appsettings.json for options.)
The following approach is required if you want to use the same log factory for DBContext that the rest of the ASP.NET MVC web app uses:
Create a derived class of DbContext (or, if this was already done, modify the existing class appropriately). Note: this example will only log SQL in Debug builds, not Release builds.
public class DbContextWithLogging : Microsoft.EntityFrameworkCore.DbContext
{
ILoggerFactory _loggerFactory;
IConfiguration _configuration; // Provides access to appsettings.json
public DbContextWithLogging(ILoggerFactory loggerFactory, IConfiguration configuration)
=> (_loggerFactory, _configuration) = (loggerFactory, configuration);
protected override void OnConfiguring(DbContextOptionsBuilder builder)
{
#if DEBUG
builder.UseLoggerFactory(_loggerFactory);
// This line causes parameter values to be logged:
builder.EnableSensitiveDataLogging();
#endif
}
}
Note: this approach is not compatible with calling AddDbContext in Startup.ConfigureServices, so if there is already a call to AddDbContext, disable/remove it. In my case, the existing derived class of DbContext had a constructor that accepted (DbContextOptions<BarreleyeDbContext> options), which I removed.
In your Startup.ConfigureServices method, configure logging (e.g. to print to console) and enable the custom DbContext:
public void ConfigureServices(IServiceCollection services)
{
services.AddLogging((ILoggingBuilder builder) => {
builder.AddConsole();
});
// In ASP.NET Core apps, a Scope is created around each server request.
// So AddScoped<X, Y>() will recreate class Y for each HTTP request.
services.AddScoped<DbContext, DbContextWithLogging>();
... // leave the rest as before
}
Whatever uses DbContext (e.g. controllers, or 'repositories' in the Repository pattern) should obtain it automagically via constructor injection.
EF Core uses LogLevel.Information when printing the SQL, so you need the Information level to be enabled. If you look at your appsettings.json file, you'll want to see something like this:
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
},
In particular, EF Core log filtering can be controlled with a key like
"Microsoft.EntityFrameworkCore": "Information",
but if this key is missing, the "Microsoft" key is used instead.
This might not work! Look for a second file called appsettings.Development.json - watch out, Visual Studio might hide this file "inside" appsettings.json. If appsettings.Development.json exists, its contents override appsettings.json (at the granularity of individual keys).
Once it's working, you'll see log info that looks like this (yes, SELECT statements are logged as well as INSERT, UPDATE and DELETE):
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (0ms) [Parameters=[#__p_0='297'], CommandType='Text', CommandTimeout='30']
SELECT e.id, e.config, e.end_date, e.entity_name, e.entity_type, e.location, e.start_date
FROM entities AS e
WHERE e.id = #__p_0
LIMIT 1

Can I keep Entity Framework context as class variable?

I'm used to working the database connections where you connect/open/close as fast as possible in each method. I'm now working with the Entity Framework and so my methods all do this type of thing:
using (var context = new FooEntities()) {
// linq to sql query here
}
I've been told that with Entity Framework I can actually have that context variable be a class level variable and not have to instantiate it in each method. Is that really the case, or should I continue this pattern in each method?
I'm using version 5.0.0 of the framework if that makes a difference.
It depends on how you are expecting it to act. The only reason you'd want it to stick around is if you wanted to use the caching feature of DbContext across multiple method calls. But since its pulling connections from the Pool anyway, disposing of a DbContext shouldn't really impact performance when creating a new one.
For me personally, I create the context as close as possible and kill it as soon as possible. Thus, the Get calls should use AsNoTracking() to speed up the calls a lot if you don't care about trying to update them later. You could also create a DbContextFactory so each class could control that interaction as it sees fit. (i.e. Method A always creates a new one, but Methods B and C could share if either one called first). Though, that could cause its own issues down the road, but then you can opt into those conditions.
You can have Context as a property of a class, but you have to consider how to control the disposing of the Context. For example:
public class UnitOfWork:IDisposable
{
public DbContext Context { get; set; }
public UnitOfWork()
{
Context = null; //initialize context here
}
public void DoWorkWithContext1()
{
//anything you need
}
public void DoWorkWithContext2()
{
//anything you need
}
public void Dispose()
{
if (Context != null)
Context.Dispose();
}
}
Then you'll use the class in this way:
using (var unit= new UnitOfWork())
{
unit.DoWorkWithContext1();
unit.DoWorkWithContext2();
}

Nested DbContext due to method calls - Entity Framework

In the following case where two DbContexts are nested due to method calls:
public void Method_A() {
using (var db = new SomeDbContext()) {
//...do some work here
Method_B();
//...do some more work here
}
}
public void Method_B() {
using (var db = new SomeDbContext()) {
//...do some work
}
}
Question:
Will this nesting cause any issues? (and will the correct DbContext be disposed at the correct time?)
Is this nesting considered bad practice, should Method_A be refactored into:
public void Method_A() {
using (var db = new SomeDbContext()) {
//...do some work here
}
Method_B();
using (var db = new SomeDbContext()) {
//...do some more work here
}
}
Thanks.
Your DbContext derived class is actually managing at least three things for you here:
the metadata that describes your database and your entity model,
the underlying database connection, and
a client side "cache" of entities loaded using the context, for change tracking, relationship fixup, etc. (Note that although I term this a "cache" for want of a better word, this is generally short lived and is just to support EFs functionality. It's not a substitute for proper caching in your application if applicable.)
Entity Framework generally caches the metadata (item 1) so that it is shared by all context instances (or, at least, all instances that use the same connection string). So here that gives you no cause for concern.
As mentioned in other comments, your code results in using two database connections. This may or may not be a problem for you.
You also end up with two client caches (item 3). If you happen to load an entity from the outer context, then again from the inner context, you will have two copies of it in memory. This would definitely be confusing, and could lead to subtle bugs. This means that, if you don't want to use shared context objects, then your option 2 would probably be better than option 1.
If you are using transactions, there are further considerations. Having multiple database connections is likely to result in transactions being promoted to distributed transactions, which is probably not what you want. Since you didn't make any mention of db transactions, I won't go into this further here.
So, where does this leave you?
If you are using this pattern simply to avoid passing DbContext objects around in your code, then you would probably be better off refactoring MethodB to receive the context as a parameter. The question of how long-lived context objects should be comes up repeatedly. As a rule of thumb, create a new context for a single database operation or for a series of related database operations. (See, for example this blog post and this question.)
(As an alternative, you could add a constructor to your DbContext derived class that receives an existing connection. Then you could share the same connection between multiple contexts.)
One useful pattern is to write your own class that creates a context object and stores it as a private field or property. Then you make your class implement IDisposable and its Dispose() method disposes the context object. Your calling code news up an instance of your class, and doesn't have to worry about contexts or connections at all.
When might you need to have multiple contexts active at the same time?
This can be useful when you need to write code that is multi-threaded. A database connection is not thread-safe, so you must only ever access a connection (and therefore an EF context) from one thread at a time. If that is too restrictive, you need multiple connections (and contexts), one per thread. You might find this interesting.
You can alter your code by passing to Method_B the context. If you do so, the creation of the second db call SomeDbContext will not be necessary.
there a question an answer in stackoverflow in this link
Proper use of "Using" statement for datacontext
It is a bit late answer, but still people may be looking so here is another way.
Create class, that cares about disposing for you. In some scenarios, there would be a function usable from different places in solution. This way you avoid creating multiple instances of DbContext and you can use nested calls as many as you like.
Pasting simple example.
public class SomeContext : SomeDbContext
{
protected int UsingCount = 0;
public static SomeContext GetContext(SomeContext context)
{
if (context != null)
{
context.UsingCount++;
}
else
{
context = new SomeContext();
}
return context;
}
private SomeContext()
{
}
protected bool MyDisposing = true;
protected override void Dispose(bool disposing)
{
if (UsingCount == 0)
{
base.Dispose(MyDisposing);
MyDisposing = false;
}
else
{
UsingCount--;
}
}
public override int SaveChanges()
{
if (UsingCount == 0)
{
return base.SaveChanges();
}
else
{
return 0;
}
}
}
Example of usage
public class ExmapleNesting
{
public void MethodA()
{
using (var context = SomeContext.GetContext(null))
{
// manipulate, save it, just do not call Dispose on context in using
MethodB(context);
}
MethodB();
}
public void MethodB(SomeContext someContext = null)
{
using (var context = SomeContext.GetContext(someContext))
{
// manipulate, save it, just do not call Dispose on context in using
// Even more nested functions if you'd like
}
}
}
Simple and easy to use.
If you think number of connections to Database,and impact of times that new connections must be opened, not an important problem and you have no limitation for support your application to run at best performance, everything is OK.
Your code works well. Because create just a db context has a low impact in your performance,meta data will be cached after first loading, and connection to your database just occurs when the code need to execute a query. With liitle performance consideration and code design, I offer you to make context factory to have just an instance of each Db Context for each instance of your application.
You can take a look at this link for more performance considerations
http://msdn.microsoft.com/en-us/data/hh949853

unable to query EntityFramework shared dbcontext reliably

I'm trying to share a simple DbContext with 4 DbSets among multiple repositories, each of my repositories inherit from this base class
public class CodeFirstRepository : IDisposable
{
private static MyContext _ctx = new MyContext();
protected MyContext Context
{
get { return _ctx; }
}
public void Dispose()
{
if (Context != null)
{
Context.Dispose();
}
}
}
Question: is this an appropriate way to share a connection between repositories?
I'm getting intermittent failures in my unit tests when accessing the various repositories. An exception is thrown from the repository method GetEntityByName
public IOfferResult GetEntityByName(string name)
{
return Context.Entities.Where(o => o.Name == name).FirstOrDefault()
}
Test method
Tests.Service.TestDelete
threw exception: System.ObjectDisposedException: The ObjectContext
instance has been disposed and can no longer be used for operations
that require a connection.
if the database already exists, the code executes as expected. it also works when i change the implementation of GetEntityByName(string name) to the following non-performant code
public IOfferResult GetEntityByName(string name)
{
foreach (OfferResult offer in Context.Offers)
{
if (offerName.ToLower() == offer.Name.ToLower())
{
return offer;
}
}
}
Question: what is going on here?
bear in mind that if the database exists when i run the tests i don't get the error at all.
tia,
jt
This problem is arising because you are treating the DbContext like a singleton by declaring it as a static field, but then you are treating it like it like a transient instance by disposing it as soon as any instance of CodeFirstRepository gets disposed. For example:
using (var r = new PersonRepository())
{
// do something
} // When you hit the end of this block, your static DbContext is disposed.
using (var r = new IOfferRepository())
{
r.GetEntityByName("test"); // this will fail because the context is still disposed.
}
You should not share contexts this way. If you really want all of your repositories to use a single instance of the DbContext, remove the call to Context.Dispose(). This would fix the problem you're getting right now, but it will likely introduce other problems in the future.
But I would strongly caution against using a single DbContext in a scenario where multiple threads could be trying to access it simultaneously. According to the DbContext specs:
Any instance members are not guaranteed to be thread safe.
You'd be better off just removing the static keyword from your field.