Reputation: 2194
I created a context using Scaffold-DbContext
Scaffold-DbContext "Server=******.database.windows.net;Database=first_choice_main; User ID = ****; Password=****" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models\Azure\Main
It created the following Context in the Models\Azure\Main folder:
namespace firstChoicePortal.Models.Azure.Main
{
public partial class First_choice_mainContext : DbContext
{
public virtual DbSet<BlobsDetails> BlobsDetails { get; set; }
public virtual DbSet<BranchInfo> BranchInfo { get; set; }
public virtual DbSet<BranchMatrix> BranchMatrix { get; set; }
public virtual DbSet<CommEventLog> CommEventLog { get; set; }
public virtual DbSet<CommEventTypes> CommEventTypes { get; set; }
public virtual DbSet<ContainerEvents> ContainerEvents { get; set; }
public virtual DbSet<ContainerEventTypes> ContainerEventTypes { get; set; }
public virtual DbSet<Containers> Containers { get; set; }
public virtual DbSet<ContainerScans> ContainerScans { get; set; }
public virtual DbSet<Customers> Customers { get; set; }
public virtual DbSet<Drivers> Drivers { get; set; }
public virtual DbSet<ExcludedPoints> ExcludedPoints { get; set; }
public virtual DbSet<FilesToFtp> FilesToFtp { get; set; }
public virtual DbSet<FtpEventLog> FtpEventLog { get; set; }
public virtual DbSet<IncomingTngReturnScans> IncomingTngReturnScans { get; set; }
public virtual DbSet<ItemTypes> ItemTypes { get; set; }
public virtual DbSet<LinehaulTracker> LinehaulTracker { get; set; }
public virtual DbSet<MaintEventTypes> MaintEventTypes { get; set; }
public virtual DbSet<NewgisticsScans> NewgisticsScans { get; set; }
public virtual DbSet<OutgoingUpdateQueue> OutgoingUpdateQueue { get; set; }
public virtual DbSet<PodDetail> PodDetail { get; set; }
public virtual DbSet<PodUpdatesSentDetail> PodUpdatesSentDetail { get; set; }
public virtual DbSet<PodUpdatesSentMaster> PodUpdatesSentMaster { get; set; }
public virtual DbSet<PointMaintEvents> PointMaintEvents { get; set; }
public virtual DbSet<ProgramSettings> ProgramSettings { get; set; }
public virtual DbSet<ReceiveScanEventTypes> ReceiveScanEventTypes { get; set; }
public virtual DbSet<ReceiveScanLog> ReceiveScanLog { get; set; }
public virtual DbSet<ReceiveScans> ReceiveScans { get; set; }
public virtual DbSet<RepAssignedStopMatrix> RepAssignedStopMatrix { get; set; }
public virtual DbSet<RepInfo> RepInfo { get; set; }
public virtual DbSet<ScanTypes> ScanTypes { get; set; }
public virtual DbSet<StopAddressDetails> StopAddressDetails { get; set; }
public virtual DbSet<StopEventLog> StopEventLog { get; set; }
public virtual DbSet<StopEventTypes> StopEventTypes { get; set; }
public virtual DbSet<SystemsConfiguration> SystemsConfiguration { get; set; }
public virtual DbSet<Table> Table { get; set; }
public virtual DbSet<TestData> TestData { get; set; }
public virtual DbSet<TestLh> TestLh { get; set; }
public virtual DbSet<TngRmaItems> TngRmaItems { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
optionsBuilder.UseSqlServer(@"Server=*****.database.windows.net;Database=first_choice_main; User ID = *****; Password=*****");
}
}
I then created a controller using the right-click method and choosing "API Controller with actions, using EF".
This is the first part of it:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using firstChoicePortal.Models.Azure.Main;
namespace firstChoicePortal.Controllers
{
[Produces("application/json")]
[Route("api/RepInfoApi")]
public class RepInfoApiController : Controller
{
private readonly First_choice_mainContext _context;
public RepInfoApiController(First_choice_mainContext context)
{
_context = context;
}
// GET: api/RepInfoApi
[HttpGet]
public IEnumerable<RepInfo> GetRepInfo()
{
return _context.RepInfo;
}
If I run this and go to https://localhost:44325/api/RepInfoApi
I get:
InvalidOperationException: Unable to resolve service for type 'firstChoicePortal.Models.Azure.Main.First_choice_mainContext' while attempting to activate 'firstChoicePortal.Controllers.RepInfoApiController'.
So I thought maybe I needed to add this to my services in startup, I added:
services.AddDbContext < First_choice_mainContext> (options =>
options.UseSqlServer(Configuration.GetConnectionString("AuzureConnectionMain")));
But I now get a runtime error right at start up of:
"System.ArgumentException: 'AddDbContext was called with configuration, but the context type 'First_choice_mainContext' only declares a parameterless constructor. This means that the configuration passed to AddDbContext will never be used. If configuration is passed to AddDbContext, then 'First_choice_mainContext' should declare a constructor that accepts a
DbContextOptions<First_choice_mainContext>
and must pass it to the base constructor for DbContext.'"
Am I going about this the wrong way?
UPDATE AND EXPLANATION ON SOLUTION
I had a couple things missing / wrong, and as Nkosi pointed out the error message did contain the solution. But it is a bit deeper than that. What I was trying to do was to use a connection string pulled from the appsettings.json file. The tooling works 100% as it, but it hard codes your connection information directly in the datacontext with this bit of code:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
optionsBuilder.UseSqlServer(@"Server=******.database.windows.net;Database=first_choice_main; User ID = ******; Password=******");
}
}
As you can see, MS recommends removing this code and replacing it with a connection string based solution - which I almost did correctly. Almost did not quite cut it -- thanks to the SO community once again!
Upvotes: 2
Views: 3294
Reputation: 247561
The exception message spells out exactly what you need to do
'AddDbContext was called with configuration, but the context type 'First_choice_mainContext' only declares a parameterless constructor. This means that the configuration passed to AddDbContext will never be used. If configuration is passed to AddDbContext, then 'First_choice_mainContext' should declare a constructor that accepts a
DbContextOptions<First_choice_mainContext>
and must pass it to the base constructor for DbContext.
Emphasis mine
Follow the instructions and add the constructor
public partial class First_choice_mainContext : DbContext {
public First_choice_mainContext(DbContextOptions<First_choice_mainContext> options)
: base(options) {
}
//...
}
That way the context can be resolved correctly when injecting into dependent classes.
Upvotes: 4