3

Я использую сущность framework 7 и создал два проекта. Один проект как проект ASP.NET 5 Web API, а другой - проект библиотеки классов (пакет), в котором я хотел сохранить всю логику уровня доступа к данным. Таким образом, я могу использовать этот пакет для другого проекта отчетности в будущем и другие дополнительные услуги, которые я могу сделать.Как вы правильно определяете DBContext в проекте библиотеки классов?

В принципе, у меня есть простой пост в моем контроллере веб-проекта api, который вызывает функцию в моем проекте библиотеки данных. Когда функция инициирует базу данных, она заявляет, что база данных не определена, даже если она определена в обоих проектах.


ОШИБКА

{"No database providers are configured. Configure a database provider by overriding OnConfiguring in your DbContext class or in the AddDbContext method when setting up services."} 

КОД

данных проекта Библиотека: InsertPerson

public int InsertPerson(tbl_Person person) 
{ 
    using (var db = new AppContext()) 
    { 
     try 
     { 
      db.tbl_Person.Add(person); 
      db.SaveChanges(); 
      return person.PersonID; 
     } 

     catch 
     { 
      return 0; 
     } 
    } 
} 

ФАЙЛЫ КОНФИГУРАЦИИ

Web API проекта: Startup.cs

public void ConfigureServices(IServiceCollection services) 
{ 
    services.AddEntityFramework() 
     .AddSqlServer() 
     .AddDbContext<AppContext>(options => 
      options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"])); 

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

    services.AddMvc(); 
} 

Web API проекта: appsettings.json

{ 
    "Data": { 
    "DefaultConnection": { 
     "ConnectionString": "Server=localhost;Database=testDB;Trusted_Connection=True;MultipleActiveResultSets=true" 
    } 
    }, 
    "Logging": { 
    "IncludeScopes": false, 
    "LogLevel": { 
     "Default": "Verbose", 
     "System": "Information", 
     "Microsoft": "Information" 
    } 
    } 
} 

Web API проект: project.json

{ 
    "userSecretsId": "blah, 
    "version": "1.0.0-rc1-final", 
    "compilationOptions": { 
    "emitEntryPoint": true 
    }, 

    "dependencies": { 
    "DataLibrary": "", 
    "Microsoft.AspNet.Authentication.OAuthBearer": "1.0.0-beta7", 
    "Microsoft.AspNet.Http.Abstractions": "1.0.0-rc1-final", 
    "Microsoft.AspNet.Identity.EntityFramework": "3.0.0-rc1-final", 
    "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final", 
    "Microsoft.AspNet.Mvc": "6.0.0-rc1-final", 
    "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final", 
    "Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final", 
    "Microsoft.Extensions.Configuration.FileProviderExtensions": "1.0.0-rc1-final", 
    "Microsoft.Extensions.Configuration.Json": "1.0.0-rc1-final", 
    "Microsoft.Extensions.Configuration.UserSecrets": "1.0.0-rc1-final", 
    "Microsoft.Extensions.Logging": "1.0.0-rc1-final", 
    "Microsoft.Extensions.Logging.Console": "1.0.0-rc1-final", 
    "Microsoft.Extensions.Logging.Debug": "1.0.0-rc1-final", 
    "Remotion.Linq": "2.0.1" 
    }, 

    "commands": { 
    "web": "Microsoft.AspNet.Server.Kestrel" 
    }, 

    "frameworks": { 
    "dnx451": { }, 
    "dnxcore50": { } 
    }, 

    "exclude": [ 
    "wwwroot", 
    "node_modules" 
    ], 
    "publishExclude": [ 
    "**.user", 
    "**.vspscc" 
    ] 
} 

данные проект Библиотека: Startup.cs

public void ConfigureServices(IServiceCollection services) 
{ 
    services.AddEntityFramework() 
     .AddSqlServer() 
     .AddDbContext<AppContext>(options => 
      options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"])); 

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

    services.AddMvc(); 
} 

данные проект Библиотеки: AppSettings. json

{ 
    "Data": { 
    "DefaultConnection": { 
     "ConnectionString": "Server=localhost;Database=testDB;Trusted_Connection=True;MultipleActiveResultSets=true" 
    } 
    }, 
    "Logging": { 
    "IncludeScopes": false, 
    "LogLevel": { 
     "Default": "Verbose", 
     "System": "Information", 
     "Microsoft": "Information" 
    } 
    } 
} 

Проект библиотеки данных: AppContext.cs

namespace DataLibrary 
{ 
    public class AppContext : IdentityDbContext<ApplicationUser> 
    { 
     public DbSet<tbl_Person> tbl_Person { get; set; } 

     public static AppContext Create() 
     { 
      return new AppContext(); 
     } 

     protected override void OnModelCreating(ModelBuilder builder) 
     { 
      new tbl_PersonMap(builder.Entity<tbl_Person>()); 
      base.OnModelCreating(builder); 
     } 
    } 
} 
+0

Вы пытались сохранить строку подключения в App.Config? –

+0

@VijayKumbhoje config работает, иначе база данных не была бы создана, когда я запустил базу данных dnx ef update в проекте Data Library. Из того, что я видел до сих пор, я думаю, что мне нужно выяснить, как ввести настройки контекста из веб-api startup в функцию. Если я работаю только в библиотеке данных, это работает, когда проект веб-ави является проектом запуска, который он сбой – chris

+0

вы видели этот учебник? http://www.jerriepelser.com/blog/moving-entity-framework-7-models-to-external-project –

ответ

2

Похоже, ваш вопрос в примере кода является то, что вы newing вверх экземпляр контекста приложения вместо того, чтобы его решения от ServiceProvider. Когда вы инициализируете DbContext таким образом, для контекста неявно создается новый ServiceProvider, и ни одна из настроек в Startup.cs не поддерживается этим контекстом. Это шаблон, который вы хотели бы использовать, если бы вы настраивали свой контекст в OnConfiguring и не интересовались инъекцией зависимостей в остальной части вашего приложения.

В такой ситуации я ожидаю, что вы получите AppContext через инъекцию конструктора. Для такого решения вам также потребуется зарегистрировать классы уровня доступа к данным в ServiceCollection. Результат должен выглядеть немного больше, как это:

Проект библиотеки данных: AppContext.cs

namespace DataLibrary 
{ 
    public class AppContext : IdentityDbContext<ApplicationUser> 
    { 
     public DbSet<tbl_Person> tbl_Person { get; set; } 

     protected override void OnModelCreating(ModelBuilder builder) 
     { 
      new tbl_PersonMap(builder.Entity<tbl_Person>()); 
      base.OnModelCreating(builder); 
     } 
    } 
} 

проекта библиотеки данных: PersonHelper.cs API Project

namespace DataLibrary 
{ 
    class PersonHelper 
    { 
     private readonly AppContext db; 

     public PersonHelper(AppContext context) 
     { 
      db = context; 
     } 

     public int InsertPerson(tbl_Person person) 
     { 
      try 
      { 
       db.tbl_Person.Add(person); 
       db.SaveChanges(); 
       return person.PersonID; 
      } 
      catch 
      { 
       return 0; 
      } 
     } 
    } 
} 

Web : Startup.cs

public void ConfigureServices(IServiceCollection services) 
{ 
    services.AddEntityFramework() 
     .AddSqlServer() 
     .AddDbContext<AppContext>(options => 
      options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"])); 

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

    services.AddScoped<PersonHelper>(); 

    services.AddMvc(); 
} 

API проект Web: MyController.cs

[Route("api/[controller]")] 
public class MyController : Controller 
{ 
    private readonly personHelper helper; 

    public MyController(PersonHelper helper) 
    { 
     this.helper = helper; 
    } 

    // POST api/my 
    [HttpPost] 
    public void Post([FromBody]string value) 
    { 
     var person = new tbl_Person 
     { 
      // ... 
     } 

     return helper.InsertPerson(person); 
    } 
} 

вы можете даже рассмотреть вопрос о добавлении методы расширения на IServiceCollection для классов доступа на канальном уровне, чтобы помочь уменьшить дублирование в конфигурации, особенно при добавлении более общего Сервисы.

0

Я нашел способ сделать это, но я до сих пор не уверен, что это лучший способ. В файле класса, который содержит мою функцию вставки, я добавил это так, что когда он вызывается из проекта web api, appcontext из веб-api передается в проект библиотеки данных.С тем, что я не уверен, если есть более элегантный подход

public class fnCommon 
{ 
    private readonly AppContext db; 

    public fnCommon(AppContext context) 
    { 
     this.db = context; 
    } 

    public int InsertPerson(tbl_Person person) 
    { 

     try 
     { 
      db.tbl_Person.Add(person); 
      db.SaveChanges(); 
      return person.PersonID; 
     } 

     catch 
     { 
      return 0; 
     } 
    } 
} 
+0

Почему бы не поставить EF-контекст в библиотеке классов и просто передать ему строку подключения? – mason

+0

@mason Что вы имеете в виду? Я думал, что, имея его в конфиге библиотеки классов, это будет одно и то же. вы можете показать мне пример того, что вы имеете в виду? Я думаю, что я могу усложнить эту проблему хаха – chris

Смежные вопросы