I have created a simple project using ASP.Net MVC template in Visual Studion 2013 Express for Web. It does not use any authentication. Then I installed EntityFramework (v6.0.1), EntityFramework.SqlServerCompact packages.
My DbContext class is very simple:
public class EditTestContext : DbContext
{
public EditTestContext() : base("EditTestContext")
{
}
public EditTestContext(string connectionString) : base(connectionString)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer(
new DropCreateDatabaseIfModelChanges<EditTestContext>());
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Configurations.Add(new EditTestConfig());
}
}
The actual context object is created in the Unit of Work class:
public class EditTestUoW:IEditTestUoW,IDisposable
{
private DbContext dbContext;
public EditTestUoW()
{
CreateDbContext();
}
private void CreateDbContext()
{
dbContext = new EditTestContext();//NEW DBCONTEXT OBJECT IS CREATED
dbContext.Configuration.LazyLoadingEnabled = false;
dbContext.Configuration.ProxyCreationEnabled = false;
dbContext.Configuration.ValidateOnSaveEnabled = false;
}
public IRepository<EditTestModel> EditTestRepo
{
get
{
return new EFRepository<EditTestModel>(dbContext);
}
}
}
The connection string being used is:
<add name="EditTestContext" connectionString="Data Source=
|DataDirectory|EditTestDb.sdf;Max Database Size=256;
Max Buffer Size=1024;File Mode=Shared Read;
Persist Security Info=False;" providerName="System.Data.SqlServerCe.4.0" />
Now when I try to access any thing using this Context like:
var rep=UoW.EditTestRepo;
var list=rep.GetAll().ToList();
I am getting following exception on rep.GetAll() function:
System.InvalidOperationException: Sequence contains no matching element
On digging deeper, IQueryable from Repository class (DbSet<EditTest>) is throwing following exception:
The context cannot be used while the model is being created. This exception may
be thrown if the context is used inside the OnModelCreating method or if the same
context instance is accessed by multiple threads concurrently. Note that instance
members of DbContext and related classes are not guaranteed to be thread safe.
I thought it might have been caused by ninject, but it is still there even after I removed it.
What I am doing wrong here or something (some assembly reference etc.) is missing?
Well after some other search on the issue, I got this MSDN forum link. As was suggested by Rowan, I tried to manually initialize the context using following statement in my EFRepository class:
dbContext.Database.Initialize(false);
The application failed way before it was hitting the GetAll() method. But this exposed the stack trace which gave me some direction:
[InvalidOperationException: Sequence contains no matching element]
System.Linq.Enumerable.Single(IEnumerable`1 source, Func`2 predicate) +2614017
System.Data.Entity.Utilities.DbProviderManifestExtensions.GetStoreTypeFromName
(DbProviderManifest providerManifest, String name) +146
.....Other Lines.....
System.Data.Entity.Internal.InternalContext.Initialize() +31
System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType
(Type entityType) +38
System.Data.Entity.Internal.Linq.InternalSet`1.Initialize() +138
System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext() +38
System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable
.get_Provider() +99
System.Linq.Queryable.Any(IQueryable`1 source) +50
Then searching for DbProviderManifestExtensions.GetStoreTypeFromName revealed that this is the line where EF was trying to get column type. I had specified UNIQUEIDENTIFIER for my Id column:
Property(x=> x.Id).HasColumnType("UNIQUEIDENTIFIER")
Once I commented this, all was well.
Though there is a request on Codeplex to provide the proper error message in case the column type is not valid for database provider.
Related
I've been having an issue with one of my .net core services when using the join statement.
This is the problem code:
public List<Category> GetCategoryList()
{
var catlist = (from m in _mappingProductCategoryRepository.Table
join c in _categoryRepository.Table on m.CategoryId equals c.Id
select c).ToList();
return catlist;
}
and the error it throws is this:
InvalidOperationException: Cannot use multiple context instances within a single query execution. Ensure the query uses a single context instance.
Here is the relevant excerpt from my repository:
public partial class PSRepository<TEntity> : IRepository<TEntity> where TEntity : class
{
private readonly PSContext _db;
public PSRepository(PSContext PSContext)
{
_db = PSContext;
}
public virtual IQueryable<TEntity> Table => _db.Set<TEntity>();
}
And here is my context being registered in the startup.cs file
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterType<PSContext>().As<PSContext>().InstancePerDependency();
builder.RegisterGeneric(typeof(PSRepository<>)).As(typeof(IRepository<>)).InstancePerLifetimeScope();
builder.RegisterType<CategoryService>().As<ICategoryService>().InstancePerLifetimeScope();
}
I've changed the context registration from 'InstancePerDependency' to 'InstancePerLifetimeScope' so that it now looks like this:
builder.RegisterType<PSContext>().As<PSContext>().InstancePerLifetimeScope();
And it seems to have fixed the issue. So being somewhat new to .Net Core my question is whether or not this was the correct fix for the issue? Or have I created further issues for myself further down the line?
I realise I could get rid of the repository and use the context directly but I don't really want to do this.
Any help gratefully received
UPDATE: I think I've eliminated Unity from the equation. See below for more details.
UPDATE 2: I think I may have eliminated Entity Framework fro the equation. See below for more details.
I have some code that is building a unity container, but it started failing with the above error message out of the blue. It works on other people's machines, but not mine. I deleted the folder the solution was in and refreshed everything from source control to ensure I had nothing that could be causing issues (e.g. duplicate assemblies lying around from a previous build).
Here is part of my code:
public static class UnityBootstrapper
{
public static IUnityContainer Initialise()
{
Trace.WriteLine("UnityBootstrapper.Initialise()");
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
return container;
}
private static IUnityContainer BuildUnityContainer()
{
Trace.WriteLine("UnityBootstrapper.BuildUnityContainer()");
var container = new UnityContainer();
// Other dependencies are registered here
// If the following line is commented out the container is build
// but, obviously, it won't resolve this dependency.
container.RegisterType<IUserAccessEntities, UserAccessEntities>(WebRequestLifetime);
// Other dependencies are registered here
return container;
}
The code apparently fails on the call to BuildUnityContainer(), and I can see that the trace statement I put inside that method is never displayed.
However, if I comment out the line that registers the UserAccessEntities class (which was code generated from Entity Framework 5) then the container is built. Naturally, when I ask for that dependency it can't resolve it, so the code just fails elsewhere.
I've Googled for solutions and they all seem to resolve around generics and moving the generic type from the method to the class level. I can't do that as EF5 creates the class and it puts generics on the properties. e.g
DbSet<MyTable> Tables { get; set; }
The only other thing I can think of is that I've extracted an interface from the EF5 generated class called IUserAccessEntities and the problem could lie there... but I used ReSharper to generate that, so it should be perfectly aligned.
UPDATE
Just to eliminate Unity from the equation, I tried to new up the UserAccessEntities on its own
private static void TestUae()
{
var uae = new UserAccessEntities(); //container.Resolve<IUserAccessEntities>();
Trace.WriteLine("Got the entities: " + uae);
}
And the call to TestUae() fails instead.
UPDATE 2
I created a new class, AlternativeEntities based on the interface I'd previously extracted. When I try to construct that directly it has a new exception: Method 'Set' in type 'AlternativeEntities' from assembly 'UserAccess.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.
However, it does. There are two methods called set, both of which I've given a basic implementation:
public class AlternativeEntities : IUserAccessEntities
{
public DbSet<TEntity> Set<TEntity>() where TEntity : class
{
Trace.WriteLine("public DbSet<TEntity> Set<TEntity>() where TEntity : class");
return null;
}
public DbSet Set(Type entityType)
{
Trace.WriteLine("public DbSet Set(Type entityType)");
return null;
}
// Other methods and properties here.
}
I'm using Entity Framework Code First. I want to be able to inject a System.Data.Common.DbConnection object when instantiating the context that derives from System.Data.Entity.DbContext. This is so that I can pass different types of connections depending on what environment the code is running in, i.e. use System.Data.SqlClient (SQL Server) in development, System.Data.SQLite when unit testing and something else in production. The pertinent parts of Context looks like this:
public class Context : DbContext
{
public Context(DbConnection dbConnection)
: base(dbConnection, true)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<Context, Configuration>());
base.OnModelCreating(modelBuilder);
}
public DbSet<Test> Tests { get; set; }
}
That gives me the following error: The target context 'Services.Persistence.Context' is not constructible. Add a default constructor or provide an implementation of IDbContextFactory. I think this happens during model initialization when Entity Framework apparently feels it needs to new up it's own Context, independent of the IoC pattern I'm trying to achieve. The lack of a default constructor is by design. The IDbContextFactory interface is just as useless - it has to have a default constructor too.
Is Entity Framework Code First completely wedded to the idea of setting up it's config by reading a connectionstring from a config file (or alternatively getting the connectionstring passed directly) or can one work around this?
UPDATE, here's the Windsor config:
container.Register(Component
.For<DbConnection>()
.UsingFactoryMethod(() =>
new SqlConnection("Data Source=(localdb)\\v11.0;Database=ThatProject;MultipleActiveResultSets=true"))
.LifeStyle.Transient);
container.Register(Component
.For<Context>()
.UsingFactoryMethod(k => new Context(k.Resolve<DbConnection>()))
.LifeStyle.PerWebRequest);
container.Register(Component
.For<IRepository>()
.UsingFactoryMethod(k => new Repository(k.Resolve<Context>()))
.LifeStyle.PerWebRequest);
I'm pretty sure your issue is nothing to do with EF but I'm not really a user of Windsor so i cant tell you for sure what your config issue is. What I have done is to reproduce a similar configuration with ninject which works exactly as you would expect, see below:
class Program
{
static void Main(string[] args)
{
IKernel kernel = new StandardKernel();
kernel.Bind<DbConnection>().ToMethod((ctx) =>{return new SqlConnection("Data Source=(localdb)\\v11.0;Database=ThatProject;MultipleActiveResultSets=true");});
kernel.Bind<Context>().ToSelf();//not really needed
kernel.Bind<TestRepository>().ToSelf();//not really needed
kernel.Get<TestRepository>();
}
}
public class Context : DbContext
{
public Context(DbConnection dbConnection)
: base(dbConnection, true){}
public DbSet<Test> Tests { get; set; }
}
public class TestRepository
{
public TestRepository(Context c)
{
c.Tests.Add(new Test());
c.SaveChanges();
var all = c.Tests;
}
}
public class Test
{
public int Id { get; set; }
}
This means that EF isn't trying to do any funkiness with context creation (as a non-empty constructor works fine for me).
From your Windsor config I would expect you need to do something like the following however im not too sure of the exact syntax:
container.Register(Component
.For<DbConnection>()
.UsingFactoryMethod(() =>
new SqlConnection("Data Source=(localdb)\\v11.0;Database=ThatProject;MultipleActiveResultSets=true"))
.LifeStyle.Transient);
container.Register(Component
.For<Context>()
.ImplementedBySelf()//this probably isn't the correct syntax
.LifeStyle.PerWebRequest);//per request is good, i have some details around why this is good practice if you are interested
container.Register(Component
.For<IRepository>()
.ImplementedBy<ConcreteRepository>()//you arent really calling a method and creating the object yourself you are letting Windsor create the object and sort out the dependancy tree
.LifeStyle.PerWebRequest);
I am trying to use mvc-mini-profiler for db-first EF, but it is not working properly.
(note that I'm using objectcontext, not dbcontext)
Here is the list of stackoverflows I've tried:
Setup of mvc-mini-profiler for EF-db- first
How to get MVC-mini-profiler working on EF 4.1 Database First
versions:
Entity Framework: 4.3.1
MiniProfiler: 2.0.2
MiniProfiler.ef: 2.0.3
This is how I setup miniprofiler:
I've added the following stuff in Global.asax
protected void Application_BeginRequest(
{
MiniProfiler.Start();
}
protected void Application_EndRequest()
{
MiniProfiler.Stop();
}
protected void Application_Start()
{
...
MiniProfilerEF.Initialize_EF42();
}
Then configure an objectcontext,
var entityConnection = new EntityConnection(ConnectionString);
var profiledDbConnection = new EFProfiledDbConnection(entityConnection, MiniProfiler.Current);
var context = profiledDbConnection.CreateObjectContext<MyContext>();
var list = context.MyEntities.ToList();
If I execute this, the following exception occurs when running "context.MyEntities.ToList()"
[System.Data.EntityCommandCompliationException]
the message in the inner exception says:
EntityClient cannot be used to create a command definition from a store command tree.
Have I configured wrong? Any help?
thanks,
I use MiniProfiler and database first Entity Framework and it does work well. You may need to turn off the database initialization strategy inside of your database context as per this related answer: https://stackoverflow.com/a/9762989/325727
public class EmployeeContext : DbContext
{
static EmployeeContext() { Database.SetInitializer<EmployeeContext>(null); }
public IDbSet<Employee> Employees { get; set; }
}
The parameter null turns off database initialization by making sure that there is no initializer available.
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.