53

I'm having a problem that when I try to access a field in my PartsDbContext I get the following error:

System.Data.SqlClient.SqlException: 'Invalid object name 'fieldName''

It seems that this is because I'm trying to make my PartsDbContext use the same database as my ApplicationDbContext which is used with Identity. I need to know how to setup a 2nd dbcontext to work with EF core that uses/creates a different database.

I've tried creating a 2nd connection string but that gets me this error:

System.Data.SqlClient.SqlException: 'Cannot open database "PartsDb" requested by the login. The login failed. Login failed for user 'DESKTOP-4VPU567\higle'.'

Here's my code:

appsettings.json

"ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-PrecisionCustomPC-b14db89e-86ad-4855-a17f-ac64a04339aa;Trusted_Connection=True;MultipleActiveResultSets=true",
    "PartsConnection":  "Server=(localdb)\\mssqllocaldb;Database=PartsDb"
},
"Logging": {
    "IncludeScopes": false,
    "LogLevel": {
        "Default": "Warning"
    }
}

PartsDbContext.cs

public class PartsDbContext : DbContext
{
    public DbSet<PartsViewModels.Tower> Towers { get; set; }
    public DbSet<PartsViewModels.Motherboard> Motherboards { get; set; }

    public PartsDbContext(DbContextOptions<PartsDbContext> options)
        : base(options)
    {
    }
}

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddDbContext<ApplicationDbContext>(options =>
         options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    services.AddEntityFramework()
        .AddDbContext<PartsDbContext>(options =>
          options.UseSqlServer(Configuration.GetConnectionString("PartsConnection")));

    services.AddMvc();

    services.AddAuthorization(options =>
    {
        options.AddPolicy("RequireAdminRole", policy => policy.RequireRole("Admin"));
    });

    // Add application services.
    services.AddTransient<IEmailSender, AuthMessageSender>();
    services.AddTransient<ISmsSender, AuthMessageSender>();
}

AdminController.cs

[Authorize(Policy = "RequireAdminRole")]
public class AdminController : Controller
{
    private readonly PartsDbContext _context;

    public AdminController(PartsDbContext context)
    {
        _context = context;
    }

    public IActionResult Index()
    {
        return View();
    }

    public IActionResult Towers()
    {
        var model = _context.Towers.ToList();
        return View(model);
    }
}

The line var model = _context.Towers.ToList(); is where the error is showing up.

Once again. I want to setup my PartsDbContext to work with Entity Framework Core in a way that EF-Core will automatically create the database.

Joe Higley
  • 1,762
  • 3
  • 20
  • 33
  • Can you ty replacing `"PartsConnection": "Server=(localdb)\\mssqllocaldb;Database=PartsDb"` with `"PartsConnection": "Server=(localdb)\\mssqllocaldb;Database=PartsDb;Trusted_Connection=True"`? – Maria Ines Parnisari May 05 '17 at 02:31

4 Answers4

62

I figured it out. This mostly came about because I accidentally deleted the database that Identity was using and I needed to figure out how to get it back.

Apparently there's nothing wrong with my connection string the way it is. I just needed to go into the package manager and type these commands in this order:

  1. Add-Migration init -Context PartsDbContext
  2. Update-Database -Context PartsDbContext

I found this out because that is what I had to do to get my ApplicationDbContext working again and it turns out that this step is done for you when you create a new MVC Core Web Application in Visual Studio using Individual User Authentication.

So basically the steps for adding more DbContexts is to:

  1. Create a DbContext Class
  2. Create a Connection string for that DbContext in appsettings.json
  3. Add the DbContext to your configured services in Startup.cs
  4. Setup the DbContext in the controllers that will use it.
  5. Open the package manager and run the 2 lines above. (if "-Context" doesn't work try "--context"
  6. Run your program and let EntityFrameworkCore take care of the rest.
Joe Higley
  • 1,762
  • 3
  • 20
  • 33
  • 2
    Are you using the same database of multiple databases? If the former, how do you separate migrations for each context in the EFMigrationsHistory table? – dotnethaggis Jun 20 '17 at 11:53
  • 1
    I'm using multiple databases – Joe Higley Jun 21 '17 at 07:01
  • 2
    What if you have an Environment condition in startup that determines which appsettings.json connection string to use for the given context? How do you know which one pm console is going to use? – DiscipleMichael Oct 10 '17 at 19:04
  • 1
    Do you have all those steps explained better in a git project or something like that? – Alexandra Damaschin Jun 01 '18 at 10:12
  • 1
    Do you know if there's a way to set a default DbContext? So that you don't need to type -context every time? – Connor Knabe Feb 06 '20 at 16:12
  • @dotnethaggis You can use below for using seperate migration history per context `services.AddDbContext(options => options.UseSqlServer(Configuration.GetConnectionString("Connection"), x => x.MigrationsHistoryTable("__IdentityHistory")));` – Tis SaxInnit Sep 02 '20 at 09:28
  • @disciplemichael you have to use the command $env:ASPNETCORE_ENVIRONMENT="Development" (or whatever the appsettings file name is) to let EF know which environment's db you are intending to update. – Ryan Naccarato Feb 07 '22 at 19:57
  • "this step is done for you when you create a new MVC Core Web Application in Visual Studio using Individual User Authentication" this is NOT true. while the project comes with an initial migration, it does not do Update-Database by itself, so the second command is still necessary. – Emre Bener Feb 22 '23 at 07:15
4

First of all, thanks @Joe Higley answer this questions,I want to add more situation to help more people.

My situation is i'm trying to use EF-Identity and Area to create a admin panel, in my admin area own their own controller/models/views..., also contain a new DBcontext.

There is problems, if you try to context.Database.EnsureCreated(); to initialize DB there will show

System.Data.SqlClient.SqlException: 'Invalid object name 'fieldName''

Ref this link Migrations with Multiple Providers

We can use migrations and use --context to set which DbContext you want to run

In VScode you can run

dotnet ef migrations add InitialCreate --context BlogContext
dotnet ef database update

In Package Management Console you can run

Add-Migration InitialCreate -Context BlogContext
Update-Database
HanksLi
  • 91
  • 4
3

In addition to the prior comments, you can use this way:

dotnet ef migrations add InitialCreate --context MyContext

dotnet ef database update --context MyContext

or

Add-Migration InitialCreate -Context MyContext

Update-Database -Context MyContext
1

I cannot comment yet, but I would like to add to the answer.

Currently I am working my way through this tutorial: https://learn.microsoft.com/en-us/aspnet/core/tutorials/razor-pages/model?view=aspnetcore-5.0&tabs=visual-studio

But I too started out with ApplicationDbContext for Identity. So, I ran into a similar problem. Your answer helped me out, thanks!

The tutorial however suggests a cleaner way to do this.

  1. Add a data model
  2. Scaffold the data model!

This step is huge. It creates the Context class, a connection string in appsettings.json, adds the Context in Startup.cs and more. For usage of scaffolding take a look at linked tutorial.

  1. Run given commands in the PMC and you are set.
    • Add-Migration init -Context ModelContext
    • Update-Database -Context ModelContext

So, I would suggest to use scaffolding as it does the most work for you.

JayPi
  • 41
  • 5