2

I'm trying to set up a asp.net mvc with portable areas (in seperate projects) and a generic repository.

I use a IContext interface to generate the database for each context that implements that interface:

public class Context : DbContext
    {
        public List<IContext> Contexts {get;set;}

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            foreach (IContext context in Contexts)
                context.Setup(modelBuilder);
        }
    }

and the implementation of IContext:

public class TaskListContext : Context, IContext
    {
        public DbSet<Task> Tasks { get; set; }

        void IContext.Setup(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Task>().ToTable("Tasks");
            modelBuilder.Entity<Task>().HasKey(task => task.Id);            
        }
    }

When I run this code:

Context context = new Context();
            context.Contexts = new List<IContext>();
            context.Contexts.Add(new ModuleContext());

            String assemblyPath = ControllerContext.HttpContext.Server.MapPath(String.Format("~/bin/{0}", "TaskList.dll")); //it is in a seperate project.

            Assembly assembly = Assembly.LoadFrom(assemblyPath);

            var contexts = from t in assembly.GetExportedTypes()
                              where typeof(IContext).IsAssignableFrom(t)
                              select t;
            foreach (Type t in contexts)
            {
                IContext cont = (IContext)Activator.CreateInstance(t);
                context.Contexts.Add(cont);             
            }

            context.Database.CreateIfNotExists();

The database and the tables are created as expected.

But when I want to query the db with a repository pattern I get an error.

The query:

TaskListRepository Rep = new TaskListRepository();
            var task = Rep.FindBy(t => t.Id==2);

The repository:

public class TaskListRepository : GenericRepository<TaskListContext, Task>, ITaskListRepository
    {
    }

The abstract repository:

public abstract class GenericRepository<C, T> :
    IGenericRepository<T>
        where T : class
        where C : DbContext, new()
    {

        private C _entities = new C();

        public C ConcreteContext
        {

            get { return _entities; }
            set { _entities = value; }
        }

        public virtual IQueryable<T> GetAll()
        {
            IQueryable<T> query = _entities.Set<T>();
            return query;
        }

        public IQueryable<T> FindBy(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
        {

            IQueryable<T> query = _entities.Set<T>().Where(predicate);
            return query;
        }

        public virtual void Add(T entity)
        {
            _entities.Set<T>().Add(entity);
        }

        public virtual void Delete(T entity)
        {
            _entities.Set<T>().Remove(entity);
        }

        public virtual void Edit(T entity)
        {
            _entities.Entry(entity).State = System.Data.EntityState.Modified;
        }

        public virtual void Save()
        {
            _entities.SaveChanges();
        }
    }

Then I get this error:

A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 - Error Locating Server/Instance Specified)

Stack Trace:

[SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 - Error Locating Server/Instance Specified)]
   System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) +6351920
   System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() +412
   System.Data.SqlClient.TdsParser.Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, Boolean ignoreSniOpenTimeout, Int64 timerExpire, Boolean encrypt, Boolean trustServerCert, Boolean integratedSecurity) +6366506
   System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, Boolean ignoreSniOpenTimeout, TimeoutTimer timeout, SqlConnection owningObject) +180
   System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, Boolean redirectedUserInstance, SqlConnection owningObject, SqlConnectionString connectionOptions, TimeoutTimer timeout) +6366917
   System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(SqlConnection owningObject, TimeoutTimer timeout, SqlConnectionString connectionOptions, String newPassword, Boolean redirectedUserInstance) +6366793
   System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, Object providerInfo, String newPassword, SqlConnection owningObject, Boolean redirectedUserInstance) +352
   System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection) +831
   System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnection owningConnection, DbConnectionPool pool, DbConnectionOptions options) +49
   System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject) +6368598
   System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject) +78
   System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject) +2194
   System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection) +89
   System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) +6372110
   System.Data.SqlClient.SqlConnection.Open() +300
   System.Data.SqlClient.SqlProviderServices.UsingConnection(SqlConnection sqlConnection, Action`1 act) +132
   System.Data.SqlClient.SqlProviderServices.UsingMasterConnection(SqlConnection sqlConnection, Action`1 act) +3981391
   System.Data.SqlClient.SqlProviderServices.GetDbProviderManifestToken(DbConnection connection) +10513049
   System.Data.Common.DbProviderServices.GetProviderManifestToken(DbConnection connection) +44

[ProviderIncompatibleException: The provider did not return a ProviderManifestToken string.]
   System.Data.Common.DbProviderServices.GetProviderManifestToken(DbConnection connection) +11121429
   System.Data.Entity.ModelConfiguration.Utilities.DbProviderServicesExtensions.GetProviderManifestTokenChecked(DbProviderServices providerServices, DbConnection connection) +94

[ProviderIncompatibleException: An error occurred while getting provider information from the database. This can be caused by Entity Framework using an incorrect connection string. Check the inner exceptions for details and ensure that the connection string is correct.]
   System.Data.Entity.ModelConfiguration.Utilities.DbProviderServicesExtensions.GetProviderManifestTokenChecked(DbProviderServices providerServices, DbConnection connection) +357
   System.Data.Entity.ModelConfiguration.Utilities.DbConnectionExtensions.GetProviderInfo(DbConnection connection, DbProviderManifest& providerManifest) +108
   System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection) +118
   System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext) +237
   System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input) +279
   System.Data.Entity.Internal.LazyInternalContext.InitializeContext() +888
   System.Data.Entity.Internal.InternalContext.Initialize() +50
   System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType) +45
   System.Data.Entity.Internal.Linq.InternalSet`1.Initialize() +151
   System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext() +50
   System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable.get_Provider() +140
   System.Linq.Queryable.Where(IQueryable`1 source, Expression`1 predicate) +135
   MonackFr.Repository.GenericRepository`2.FindBy(Expression`1 predicate) in D:\code\MonackFr\MonackFr\MonackFr.Library\Repository\GenericRepository.cs:34
   MonackFr.Mvc.Areas.TaskList.Controllers.TaskController.Index() in D:\code\MonackFr\MonackFr\MonackFr.Mvc\MonackFr.Mvc\Areas\TaskList\Controllers\TaskController.cs:18
   lambda_method(Closure , ControllerBase , Object[] ) +113
   System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +261
   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +39
   System.Web.Mvc.Async.<>c__DisplayClass42.<BeginInvokeSynchronousActionMethod>b__41() +34
   System.Web.Mvc.Async.<>c__DisplayClass39.<BeginInvokeActionMethodWithFilters>b__33() +129
   System.Web.Mvc.Async.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49() +954935
   System.Web.Mvc.Async.<>c__DisplayClass37.<BeginInvokeActionMethodWithFilters>b__36(IAsyncResult asyncResult) +15
   System.Web.Mvc.Async.<>c__DisplayClass2a.<BeginInvokeAction>b__20() +33
   System.Web.Mvc.Async.<>c__DisplayClass25.<BeginInvokeAction>b__22(IAsyncResult asyncResult) +955452
   System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__18(IAsyncResult asyncResult) +28
   System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +20
   System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +67
   System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +20
   System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +53
   System.Web.Mvc.<>c__DisplayClassb.<BeginProcessRequest>b__4(IAsyncResult asyncResult) +42
   System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +20
   System.Web.Mvc.<>c__DisplayClasse.<EndProcessRequest>b__d() +54
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +469
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +375

Connection String:

<connectionStrings>
      <add name="Context" providerName="System.Data.SqlClient" connectionString="Data Source=localhost;Initial Catalog=monackfr;User Id=sa;Password=*******" />       
  </connectionStrings>

I really don't see it anymore? Does anyone know what's going wrong? The connectionstring should be correct: it is making the database and tables.

Regards,

Willem

5
  • Have you observed the connection the context is trying to use by logging or just debugging inside of your Generic repo? Also, why is the context not being injected? Commented Jul 16, 2012 at 22:04
  • Can you show the connection string section of your web.config? Commented Jul 17, 2012 at 0:20
  • the connection from the context the generic repo is using: "Data Source=.\\SQLEXPRESS;Initial Catalog=MonackFr.Mvc.Areas.TaskList.TaskListContext;Integrated Security=True;MultipleActiveResultSets=True;Application Name=EntityFrameworkMUE" Commented Jul 17, 2012 at 5:16
  • Willem did u resolve the exception? Commented Dec 24, 2012 at 21:48
  • I Did, see below: I inherited the TaskListContect from Contect and IContext and added public TaskListContext() { Database.SetInitializer<TaskListContext>(null); } Commented Dec 25, 2012 at 20:30

1 Answer 1

1

EF has a lots of useful conventions. One of them is that EF tries to find out the connection string automatically.

If you haven't specify otherwise and there is no connection string in your config file EF will creates one with the DB name based on the DbContext type's name.

So when you use Context it can find your connection string with name="Context" in your config. But when you use TaskListContext it could not find a connection string with name='TaskListContext' so it will geneate a connection string for you which will result in the exception what you get.

To avoid this you can add a new connection string with the name='TaskListContext' in your app/web.config

Or you can use one of the DbContext contructor overloads to specify the connection excplicitly. With your current design it should look like this:

public class Context : DbContext
{
    public Context()
    {
    }

    public Context(string nameOrConnectionString) : base(nameOrConnectionString)
    {
    }

    //.. rest of Context 
}

public class TaskListContext : Context, IContext
{
    public TaskListContext() : base("Context")
    {
    }

     //.. rest of TaskListContext 
}

With this modification in all the IContext derived types EF will use the same connection string named "Context" from your config file for every DbContext.

Sign up to request clarification or add additional context in comments.

2 Comments

Since I want to use the same connection in all contexts I added public Context() : base("Context") { } to the Context class, which works as expected: the connection string is correct, but now EF starts complaining that the database has changed: The model backing the 'TaskListContext' context has changed since the database was created. Consider using Code First Migrations to update the database.
I found the answer for that one too. I use this in the constructor of each context: Database.SetInitializer<Context>(null); Thanks a lot for the answers, you really helped me out!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.