.Net Core Web API с EF

Я новичок как в .Net Core, так и в Entity Framework. Я пытаюсь изучить обе технологии, следуя некоторому руководству, но я борюсь. В моем проекте веб-API есть два контроллера: мастер сгенерировал ValuesController.cs, который создается при создании нового проекта Core Web API, и второй добавленный мной контроллер под названием FilesController.cs.

Мой appsettings.json:

{
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  },

  "ConnectionStrings": {
    "    \"PropWorxConnection\"": "server=a.b.com;user id=propworx;persistsecurityinfo=True;database=abcde;password=12345"
  }
}

Мой Startup.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using MySQL.Data.EntityFrameworkCore.Extensions;

namespace PropWorxAPI
{
    public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                .AddEnvironmentVariables();
            Configuration = builder.Build();
        }

        public IConfigurationRoot Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.AddDbContext<Models.PropWorxDbContext>(options =>
                options.UseMySQL(Configuration.GetConnectionString("PropWorxConnection")));
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            app.UseMvc();
        }
    }
}

Простая модель:

namespace PropWorxAPI.Models
{
    [Table("files")]
    public partial class File
    {
        public int ID { get; set; }
        public string FileNum { get; set; }
    }
}

Мой контекст:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using MySQL.Data.EntityFrameworkCore.Extensions;

namespace PropWorxAPI.Models
{
    public class PropWorxDbContext : DbContext
    {
        private readonly string _connectionString;

        public PropWorxDbContext(string connectionString)
        {
            _connectionString = connectionString;
        }

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

        public DbSet<Models.File> Files { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Models.File>().ToTable("Files");
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseMySQL(_connectionString);
            base.OnConfiguring(optionsBuilder);
        }
    }
}

и мой контроллер:

using Microsoft.AspNetCore.Mvc;
using PropWorxAPI.Models;

namespace PropWorxAPI.Controllers
{
    [Route("api/[controller]")]
    public class FilesController : Controller
    {
        private readonly PropWorxDbContext _context;

        public FilesController(PropWorxDbContext context)
        {
            _context = context;
        }

        [HttpGet]
        public string Get()
        {
            return "Controller Working!!!";
        }
    }
}

Теперь, когда я запускаю его (F5), он открывает Edge и переходит на http://localhost:51932/api/values. Это отображает этот вывод:

["значение1", "значение2"]

Так что по умолчанию используется ValuesController (как это изменить ???). В любом случае, важно то, что автоматически сгенерированный ValuesController работает. Теперь я вручную изменяю URL-адрес, чтобы указать на созданный мной FilesController, т.е.

http://localhost:51932/api/files

... и я получаю это:

Ошибка HTTP 500 Странно ... веб-сайт не может отображать эту страницу

Теперь, если я удалю аргумент контекста из моего FilesController, т.е. я перейду из:

public FilesController(PropWorxDbContext context)
        {
            _context = context;
        }

to

public FilesController()
        {
        }

тогда он работает и правильно отображает:

это файловый контроллер

Есть идеи, почему? Спасибо и извините за слишком многословный пост ...


person Fabricio Rodriguez    schedule 12.01.2017    source источник


Ответы (3)


Удалите эти две строки из метода OnConfiguring.

optionsBuilder.UseMySQL(_connectionString);
base.OnConfiguring(optionsBuilder);

Вы уже говорите провайдеру в ConfigureServices методе startup.cs

services.AddDbContext<Models.PropWorxDbContext>(options =>
options.UseMySQL(Configuration.GetConnectionString("PropWorxConnection")));

Обновленный DbContext

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using MySQL.Data.EntityFrameworkCore.Extensions;

namespace PropWorxAPI.Models
{
    public class PropWorxDbContext : DbContext
    {

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

        public DbSet<Models.File> Files { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Models.File>().ToTable("Files");
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {

        }
    }
}
person Ahmar    schedule 12.01.2017
comment
Большое спасибо за быстрый ответ. Хорошо, я закомментировал эти две строки, но все равно выдаю ту же ошибку :( - person Fabricio Rodriguez; 13.01.2017
comment
Если я удалю аргумент DbContext из конструктора FilesController, он больше не выдаст ошибку. Но, очевидно, это мне не поможет, так как теперь у меня нет доступа к контексту в моем файле контроллера ... - person Fabricio Rodriguez; 13.01.2017
comment
не нужно удалять с контроллера, комментируйте только те строки, которые я упоминаю в ответе. - person Ahmar; 13.01.2017

Ваша инъекция зависимости не работает. Когда фреймворк пытается создать новый FilesController, он не может, потому что не знает, что такое PropWorxContext.

namespace PropWorxAPI.Models
{
    public class PropWorxDbContext : DbContext
    {
        private readonly string _connectionString;

        //public PropWorxDbContext(string connectionString)
        //{
        //    _connectionString = connectionString;
        //}

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

        public DbSet<Models.File> Files { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Models.File>().ToTable("Files");
        }

        //protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        //{
        //    optionsBuilder.UseMySQL(_connectionString);
        //    base.OnConfiguring(optionsBuilder);
        //}
    }
}

Вам не нужна строка подключения или переопределение OnConfiguring, потому что вы делаете это в своем Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    // This must come before MVC
    services.AddDbContext<Models.PropWorxDbContext>(options => options.UseMySQL(Configuration.GetConnectionString("PropWorxConnection")));

    services.AddMvc();

}

Строка services.AddDbContext регистрирует вашу базу данных с помощью внедрения зависимостей. Это позволяет вашему контроллеру работать с правильным конструктором.

public FilesController(PropWorxDbContext context)
{
    _context = context;
}

Я думаю, что единственная проблема, которая у вас есть, - это ненужный код в вашем DbContext, который не позволяет контейнеру внедрения зависимостей обновлять его.

person Woot    schedule 12.01.2017
comment
Большое спасибо за быстрый ответ. Хорошо, я закомментировал оба места (общедоступный PropWorxDbContext (string connectionString) и OnConfiguring), но все же дал мне ту же ошибку :( - person Fabricio Rodriguez; 13.01.2017
comment
Если я удалю аргумент DbContext из конструктора FilesController, он больше не выдаст ошибку. Но, очевидно, это мне не поможет, так как теперь у меня нет доступа к контексту в моем файле контроллера ... - person Fabricio Rodriguez; 13.01.2017
comment
@ user1900799 вам нужно переместить туда, куда вы поместили встроенные сервисы.AddDbContext ‹Models.PropWorxDbContext› (options = ›options.UseMySQL (Configuration.GetConnectionString (PropWorxConnection))); Это должно произойти до services.AddMvc (); См. Мои изменения в Startup.cs - person Woot; 13.01.2017

Выяснил это - мои ConnectionStrings в appsettings.json не были отформатированы правильно (у меня были странные косые черты - не знаю, почему ... спасибо за вашу помощь, хотя Ахмар и user1900799 - искренне признательны!

person Fabricio Rodriguez    schedule 13.01.2017