1

According to this tutorial I should:

Register your context with dependency injection

The Tutorial describes that I should locate the method ConfigureServices() and put in there the code advised.

Here's my startup.cs:

using Microsoft.Owin;
using Owin;

[assembly: OwinStartupAttribute(typeof(MyProject.Startup))]
namespace MyProject
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
        }
    }
}

so I don't know where to correctly put the code.

Because the project isn't compatible with .net core 2.1, it was needed to change Project->Property to .Net Framework 4.6.1 and install packages Microsoft.EntityFrameworkCore.SqlServer and Microsoft.EntityFrameworkCore.Tools

I tried to add the dependency injection to global.asax.cs file as follows:

protected void Application_Start()
        {
            var services = new ServiceCollection();
            ConfigureServices(services);
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
}

private void ConfigureServices(IServiceCollection services)
    {
        var connection = @"Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True;ConnectRetryCount=0";
        services.AddDbContext<BloggingContext>(options => options.UseSqlServer(connection));
    }

I succeeded with the step and created the controller and it works, but I haven't chosen the right context (BloggingContext), so it created second database. So, I need to create a controller with BloggingContext, do you know how?

ArunPratap
  • 4,816
  • 7
  • 25
  • 43
xralf
  • 3,312
  • 45
  • 129
  • 200
  • You can add the method your self. `Startup` class is part of the start up convention. – Nkosi Aug 08 '19 at 12:56
  • 1
    The version of the shown startup and the tutorial are in conflict with each other. – Nkosi Aug 08 '19 at 13:10
  • @Nkosi I changed in Project->Property to .Net Framework 4.6.1 – xralf Aug 08 '19 at 13:11
  • @Nkosi it was needed to install in PMC Microsoft.EntityFrameworkCore.SqlServer and Microsoft.EntityFrameworkCore.Tools as well – xralf Aug 08 '19 at 13:13
  • You should try Ninject for dependency injection. It works fine with .Net Framework 4.6. Implementation of dependency injection differs for .Net core and .Net. Am not sure it is fully integrated in .Net Framework as .Net core has. you might need Ninject or Unity – Bosco Aug 12 '19 at 17:26
  • @Bosco [Here](https://stackoverflow.com/questions/45222923/asp-net-classic-owin-startup-configureservices-not-called/54237510#54237510) is written that it should work. – xralf Aug 12 '19 at 17:32
  • You have regular MVC project but you want to use EF Core, why? Use EF 6 and see tutorials for ASP.NET MVC ninject – Alexander Aug 12 '19 at 19:17
  • The context you see while creating a controller in design view are registered in the web.config, again instantiating `BlogContext` in a controller defeats the aim of DI you should use Interfaces. the `ConfigureService` is added in the Startup.cs – Bosco Aug 12 '19 at 21:31
  • Are you using .Net Framework or .Net Core? I suggest you to search for the differences. If finally you want to use .Net Core, I suggest you to use .net core in all your searches. – Oscar Vicente Perez Aug 13 '19 at 07:44
  • Is there a particular reason you need to mix the two technologies? Why not use a .NET Framework DI package like Autofac / StructureMap etc. These all work fine injecting a DbContext via constructor injection. – ste-fu Aug 13 '19 at 08:52
  • @ste-fu please write it as an answer, so I can try, if it will find the BloggingContext – xralf Aug 13 '19 at 12:05

4 Answers4

2

The version of the shown startup and the tutorial are in conflict with each other.

If this if for an Asp.Net Core MVC application then you can add the method your self. Startup class is part of the convention.

public partial class Startup {
    //...

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
         //...
    }
}

Reference App startup in ASP.NET Core

The ConfigureServices method

The ConfigureServices method is:

  • Optional.
  • Called by the host before the Configure method to configure the app's services.
  • Where configuration options are set by convention.

If however you are trying to use .Net Core technologies in an Asp.Net MVC 5+ (which is what the GitHub project targets) then you will need to modify your approach to adapt to using .Net Core Dependency Injection with a non core platform.

First you will need a IDependencyResolver which is the DI framework used by that version of Asp.Net MVC, and a way to replace the default resolver with your own.

public sealed class CoreDependencyResolver : System.Web.Mvc.IDependencyResolver {
    private readonly System.Web.Mvc.IDependencyResolver mvcInnerResolver;
    private readonly IServiceProvider serviceProvider;

    public CoreDependencyResolver(IServiceProvider serviceProvider, System.Web.Mvc.IDependencyResolver dependencyResolver) {
        this.serviceProvider = serviceProvider;
        mvcInnerResolver = dependencyResolver;
    }

    public object GetService(Type serviceType) {
        object result = this.serviceProvider.GetService(serviceType);
        if (result == null && mvcInnerResolver != null)
            result = mvcInnerResolver.GetService(serviceType);
        return result;
    }

    public IEnumerable<object> GetServices(Type serviceType) {
        IEnumerable<object> result = this.serviceProvider.GetServices(serviceType);
        if (result == null && mvcInnerResolver != null)
            result = mvcInnerResolver.GetServices(serviceType);
        return result ?? new object[0];
    }
}

With the custom resolver in place, you can now configure the application to use it.

Using your current example as a starting point (review comments)

protected void Application_Start() {
    var services = new ServiceCollection();
    ConfigureServices(services);
    //build service provider
    IServiceProvider provider = services.BuildServiceProvider();
    //Get the current resolver used by MVC
    var current = DependencyResolver.Current;
    //use that and the provider to create your custom resolver
    var resolver = new CoreDependencyResolver(provider, current);
    //now set the MVC framework to use the resolver that wraps the service provider
    //that was created from .Net Core Dependency Injection framework.
    DependencyResolver.SetResolver(resolver);
    //...

    AreaRegistration.RegisterAllAreas();
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}

private void ConfigureServices(IServiceCollection services) {
    //... omitted for brevity (register dependencies as normal)
}
Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • Thanks but there are a few red lines in my code. Could you show the full method with the namespaces as well? – xralf Aug 08 '19 at 13:04
  • @xralf just noticed a discrepancy. The tutorial is for Core while the other code is for previous version of MVC. Can you clarify what version you are using. – Nkosi Aug 08 '19 at 13:06
  • I changed the .net framework to 4.6.1 in Project->Properties, without it it would not work. – xralf Aug 08 '19 at 13:07
  • it was needed to install in PMC Microsoft.EntityFrameworkCore.SqlServer and Microsoft.EntityFrameworkCore.Tools as well – xralf Aug 08 '19 at 14:13
  • When I paste into ConfigureServices() only these two lines of code var connection = @"Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True;ConnectRetryCount=0"; services.AddDbContext(options => options.UseSqlServer(connection)); I have problem creating a controler. It won't offer me BloggingContext – xralf Aug 08 '19 at 14:20
  • Here's my [global.asax.cs](https://pastebin.com/RNy0sMLi) file. After Build->Clean, Build->Rebuild, right click controllers->add->controller->MVC 5 controller with views, using entity framework... in Data Context Class I can't choose BloggingContext – xralf Aug 13 '19 at 12:26
  • Blogging3 is just a typo. – xralf Aug 13 '19 at 12:50
1

Here I am using Oracle, but you could do the same with SQL Server...

 public void ConfigureServices(IServiceCollection services)
 {

        services.AddEntityFrameworkOracle()
            .AddDbContext<OracleDbContext>(builder => builder.UseOracle(Configuration["Data:OracleDbContext"]),ServiceLifetime.Scoped)
            .AddDbContext<AppsDbContext>(option => option.UseOracle(Configuration["Data:AppsDbConnection:ConnectionString"]), ServiceLifetime.Scoped);

Then in my appsettings.json, I include the connection strings...

"Data": {
"OracleDbContext": "your connection string" },
"AppsDbContext": "your connection string" }
 }
Charles Owen
  • 2,403
  • 1
  • 14
  • 25
1

It appears you're using .Net Framework, rather than .Net Core.

2 simple ideas here:

A. Nadjar
  • 2,440
  • 2
  • 19
  • 20
0

Whilst using .NET Core tooling with full framework works quite well, if you have to use MVC5 and full framework I would not try to work it that way round.

There are many .NET 4.6.1 dependency injection frameworks, in this example I will use Autofac.

  • Install the NuGet packages Autofac and Autofac.Mvc5.
  • Add an AutofacRegistration.cs class to the App_Start folder
  • In the Application_Start() method in Global.asax add the line AutofacRegistration.BuildContainer();

Your AutofacRegistration class is where you wire up all your dependencies for dependency injection. The full docs are here https://autofaccn.readthedocs.io/en/latest/integration/mvc.html

public class AutofacRegistration
{
    public static void BuildContainer()
    {
        var builder = new ContainerBuilder();

        // Register your MVC controllers
        builder.RegisterControllers(typeof(MvcApplication).Assembly);

        // Now grab your connection string and wire up your db context
        var conn = ConfigurationManager.ConnectionStrings["BloggingContext"];
        builder.Register(c => new BloggingContext(conn));

        // You can register any other dependencies here

        // Set the dependency resolver to be Autofac.
        var container = builder.Build();
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
    }
}

This is assuming your BloggingContext has a constructor that takes the connection string as a parameter and passes it to the base class. Something like

public class BloggingContext : DbContext
{
    public BloggingContext(string connectionString) : base(connectionString)
    {
    }
}

There is loads more in the documentation about scope etc that is worth reading but this should be the nuts and bolts of it.

ste-fu
  • 6,879
  • 3
  • 27
  • 46
  • Thank you, I will try tomorrow. Could you tell me what's "MyDbContext"? It's my connection string? And MyDbContext = BloggingContext? – xralf Aug 13 '19 at 17:48
  • 1
    Yes. I've called them the same thing, but one is the name of the connection string and one is your implementation of DbContext, which would be BloggingContext – ste-fu Aug 14 '19 at 06:05
  • There is red underline in the builder.Register(c => new BloggingContext(conn); ... conn is underlined as an error – xralf Aug 14 '19 at 12:24
  • Ok - another assumption. I assumed you had implemented the constructor with a string parameter...see update – ste-fu Aug 14 '19 at 13:00
  • Here is my [autofacRegistration.cs](https://pastebin.com/en1SQKv3) file and [bloggingContext.cs](https://pastebin.com/UaGdZLb3) file. After Build->Clean, Build->Rebuild, right click controllers->add->controller->MVC 5 controller with views, using entity framework... in Data Context Class I can't choose BloggingContext – xralf Aug 14 '19 at 13:40
  • Ok - remove all references to Entity Framework core and make sure you reference Entity Framework 6.x. Remove all but the parameterless constructor for your BloggingContext and add one with just a string as per my example – ste-fu Aug 15 '19 at 07:26
  • Which nuget packages do I need to install to be able to use the command: Scaffold-DbContext "Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Tables Blog,Post Or some similar command – xralf Aug 15 '19 at 12:17
  • Thanks to you, I have found [this](https://learn.microsoft.com/cs-cz/aspnet/mvc/overview/getting-started/database-first-development/) tutorial, which works with the project. I wasn't able to find it before. – xralf Aug 15 '19 at 13:42