简体   繁体   中英

MVC 4 Database First project: Setting DBContext for the life of the controller

I am not sure that the title of my thread really explains what I am trying to do, so I will better explain it here. I am new to MVC and I have a project that I am working on. I am connecting to a Firebird database and, as of right now, I am setting up the connection string and the connection itself within the Index() of one of the controllers. This is fine in that the connection is created and it returns my list to the View as it should. I can go back into my View and I can select another database and it will connect to the new database and display the results as normal. I realize that the better way to do this is to create a DAL class, I am sure, but for now, bear with me.

All this works wonderfully. Where I hit a snag (as you might imagine) is when I try to Edit, Save, or Delete anything. Obviously, those methods are looking at the dbContext and nothing has changed with the DBContext. The DBContext is not necessarily "updated" by my connection code. I can create the connection when I want to, but I cannot "set" it for the life of the controller, as it were.

Basically, I am just asking for some advice. I have been scouring StackOverflow and I think I have found some information that might help me, but it is a little over my head still. Just trying to get a grasp on using the DBcontext to dynamically change my connection string for the entire controller, not just the Index().

Thanks in advance.

EDITED TO SHOW CONTEXT CODE

public partial class Entities : DbContext
{

    public Entities()
        : base("name=Entities")
    {
    }

    public Entities(string providerString)
        : base(new FbConnection(providerString), true)
    {
        this.Database.Connection.ConnectionString = providerString;
    }

This gives an error upon the return View(); of the Index.

UPDATED CONTROLLER CODE:

            FbConnectionStringBuilder fbBuilder = new FbConnectionStringBuilder()
            {
                DataSource = dbsource,
                Database = dbdir,
                UserID = dbuser,
                Password = dbpwd,
                Dialect = 3,
                PacketSize = 8192
            };

            // Build the FbConnection connection string.
            FbConnection fbConn = new FbConnection(fbBuilder.ToString());

            db = new Entities(fbConn.ToString());

UPDATED DBCONTEXT:

public partial class Entities : DbContext
{

    public Entities(string fbConn)
        : base(new FbConnection(fbConn), true)
    {
    }

However, this now produces the error:

An invalid connection string argument has been supplied or a required connection string argument has not been supplied.

But this doesn't make sense, because if I use this.Database.Connection.ConnectionString, then I can connect, so I know it is getting a good string.

Two options:

Easiest

Add a property to the controller to hold your DbContext , then add a parameterless ctor that will populate is (effectively giving it a lifespan of that of the controller). eg

public class MyController : Controller
{
    private readonly DbContext context;
    public MyController()
    {
        this.context = new DbContext();
    }

    // rest of actions reference `context.<whatever>`
}

More Involved

Introduce Inversion of Control (IoC) in to the equation with some form of Dependency Injector (DI). Then, let the resolver place the context in the controller when it's instantiated. The new controller signature then looks like:

public class MyController : Controller
{
    private readonly DbContext context;
    public MyController(DbContext context)
    {
        this.context = context;
    }

    // rest of actions reference `context.<whatever>`
}

Note: The parameterless ctor went away, but your DependencyResolver will automatically insert the correct instance in when the controller's created.

From there, you need to declare which instance in the DI's configuration. Using ninject as an example, something like:

kernel.Bind<DbContexT>().To<MyDbContext>()
    // here's where scope comes in to play:
    // for ninject: https://github.com/ninject/ninject/wiki/Object-Scopes
    //.InTransientScope();
    //.InSingletonScope();
    //.InThreadScope();
    //.InRequestScope();

Fixed by adding some workarounds. Added code below:

Model.context.cs:

    public MyDatabaseContext()
        : base("name=MyDatabaseContextEntities")
    {
    }

    public MyDatabaseContext(string connectionString)
        : base("name=MyDatabaseContextEntities")
    {
        this.Database.Connection.ConnectionString = connectionString;
    }

Controller:

    public static string temporaryConnectionString
    {
        get;
        set;
    }

    FbConnectionStringBuilder fbBuilder = new FbConnectionStringBuilder()
    {
          //code to build your connection
    };

    //connectionString defined as a public variable
    connectionString = fbBuilder.ToString();

    //store to session variable in your DAL
    context.DataConnection.DAL.CurrentConnection = connectionString;
    temporaryConnectionString = connectionString;
    context = new MyDatabaseContext(connectionString);

    return View();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM