2

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!

1 Answer 1

4

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.

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

2 Comments

Thank you - I will accept this answer as it 100% fixes the problem. I do not understand why the default tooling does not / did not create this? Was there something I should have done differently with my Scaffold-DbContext command? I don't recall having to manually modify my context I have created before, but I have been working with Postgresql before vs sql server.
OK...I was confused as to why the tooling did not create this in the first place. I will update my question to reflect what I have learned in case anybody else trips up over this.

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.