.Net Web Api: зачем мне устанавливать Entity Framework в свой проект контроллеров Web Api?

У меня есть многоуровневый проект .Net Web Api, где (помимо самого уровня Web Api) у меня есть DAL, который будет выполнять все операции с базой данных (я работаю с Oracle).

Для этого я настроил уровень доступа к данным с помощью NuGet и добавил следующие три пакета:

1) EntityFramework
2) Oracle.ManagedDataAccess
3) Oracle.ManagedDataAccess.EntityFramework

И определил класс сущностей, подобный следующему:

using System.Data.Entity;

public class WFRHEntities : DbContext
{
    public WFRHEntities() : base("WFRHEntities") {

        bool instanceExists = System.Data.Entity.SqlServer.SqlProviderServices.Instance != null;
    }

    public DbSet<Employee> Employees { get; set; }
    public DbSet<Vacancy> Vacancies { get; set; }

    public virtual void Commit()
    {
        base.SaveChanges();
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema("SYSTEM");
        modelBuilder.Configurations.Add(new EmployeeConfiguration());
    }

Затем в моем контроллере Web Api Vacancy у меня есть метод публикации:

[HttpPost]
public IEnumerable<string> Post([FromBody]Vacancy vacancy)
{
    if (vacancy == null)
    {
        throw new System.ArgumentNullException(nameof(vacancy));
    }
    WFRHEntities vacancyEntity = new WFRHEntities();
    vacancyEntity.Vacancies.Add(vacancy);

    return new string[] { "Vacancy request added correctly" };
}

И этот метод получает почтовый запрос из формы приложения Angular для создания нового запроса на вакансию, но не может заставить его работать, поскольку он жалуется, что необходимо установить Entity Framework.

Дело в том, что с интуитивной точки зрения (и теоретически) у вас нет причин устанавливать какие-либо элементы данных в проекте UI (или Web Api), поэтому у вас должен быть DAL.

Скажем, я бы не прочь установить Entity Framework (я использую v6.0) в проекте Web Api, но дело в том, что вдобавок ко всему этого недостаточно, так как мне также нужно добавить это в web.config:

<entityFramework>
    <defaultConnectionFactory type = "System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
    <providers>
      <provider invariantName = "Oracle.ManagedDataAccess.Client" 
                type = "Oracle.ManagedDataAccess.EntityFramework.EFOracleProviderServices, Oracle.ManagedDataAccess.EntityFramework, Version=6.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
    </providers>
  </entityFramework>

И для этого мне также нужно добавить два упомянутых выше пакета Oracle через NuGet, чтобы Entity Framework знала, что он будет работать с Oracle, а не с SQL Server, и таким образом вы начнете иметь свой пользовательский интерфейс (или веб-API), полный ссылок на вещи, связанные с данными.

Я не хочу (и я не думаю, что это хорошая идея) иметь все это где угодно, кроме DAL и FYI. Я не работаю с репозиториями и шаблонами Unit Of Work, поскольку я их не знаю, поэтому я Я стараюсь, чтобы все было просто.

Я читал следующий пост:

Почему мне нужно ссылаться на EF в моем проекте пользовательского интерфейса?

но не смог найти обходной путь (или твердое решение) моей проблемы.

Есть идеи, как это обойти?

Неужели так сложно полностью отделить пользовательский интерфейс от уровня данных?

Спасибо.

Обновлено: переписан небольшой код.

Я переписал код и создал в DAL класс VacancyRepository следующим образом:

namespace WFRH.Data
{
    public class VacancyRepository
    {
        public VacancyRepository() {

        }

        public void Add(Vacancy entity) {

            WFRHEntities vacancyEntity = new WFRHEntities();
            vacancyEntity.Vacancies.Add(entity);
        }
    }
}

После этого я удалил EntityFramework (и связанные с Oracle пакеты) из проекта Web Api и удалил все настройки данных в Web Api web.config и вызвал метод добавления в контроллере следующим образом:

[HttpPost]
public IEnumerable<string> Post([FromBody]Vacancy vacancy)
{
    if (vacancy == null)
    {
        throw new System.ArgumentNullException(nameof(vacancy));
    }
    VacancyRepository vr = new VacancyRepository();
    vr.Add(vacancy);

    return new string[] { "Vacancy request added correctly" };
}

Это мой DAL app.config

<?xml version = "1.0" encoding = "utf-8"?>
<configuration>
  <configSections>
    <section name = "entityFramework"type = "System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
      requirePermission = "false"/>
    <section name = "oracle.manageddataaccess.client"
      type = "OracleInternal.Common.ODPMSectionHandler, Oracle.ManagedDataAccess, Version=4.122.18.3, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
  </configSections>
  <system.data>
    <DbProviderFactories>
      <remove invariant = "Oracle.ManagedDataAccess.Client"/>
      <add name = "ODP.NET, Managed Driver" invariant = "Oracle.ManagedDataAccess.Client" description = "Oracle Data Provider for .NET, Managed Driver"
        type = "Oracle.ManagedDataAccess.Client.OracleClientFactory, Oracle.ManagedDataAccess, Version=4.122.18.3, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
    </DbProviderFactories>
  </system.data>
  <runtime>
    <assemblyBinding xmlns = "urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <publisherPolicy apply = "no"/>
        <assemblyIdentity name = "Oracle.ManagedDataAccess" publicKeyToken = "89b483f429c47342" culture = "neutral"/>
        <bindingRedirect oldVersion = "4.122.0.0 - 4.65535.65535.65535" newVersion = "4.122.18.3"/>
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <oracle.manageddataaccess.client>
    <version number = "*">
      <dataSources>
        <dataSource alias = "SampleDataSource" descriptor = "(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORCL))) "/>
      </dataSources>
    </version>
  </oracle.manageddataaccess.client>
  <connectionStrings>
    <add name = "OracleDbContext" providerName = "Oracle.ManagedDataAccess.Client"
      connectionString = "User Id=oracle_user;Password=oracle_user_password;Data Source=oracle"/>
  </connectionStrings>
  <entityFramework>
    <providers>
      <provider invariantName = "Oracle.ManagedDataAccess.Client"        type = "Oracle.ManagedDataAccess.EntityFramework.EFOracleProviderServices, Oracle.ManagedDataAccess.EntityFramework, Version=6.122.18.3, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
    </providers>
  </entityFramework>
</configuration>

И ошибка, которую я теперь получаю при попытке выполнить операцию добавления, следующая:

System.Data.SqlClient.SqlException: отказано в разрешении на создание базы данных в главной базе данных, поэтому теперь мои вопросы:

1) Почему он выдает исключение SQl, когда в моем файле app.config DAL ясно, что все ссылки относятся к Oracle, а не к одной ссылке на сервер Sql? 2) Почему возникает ошибка «Создать базу данных», когда я пытаюсь добавить запись в существующую таблицу?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
454
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам необходимо установить все, на что компилятору нужно будет ссылаться во время компиляции.

Ваш код Api, по-видимому, знает о WFRHEntities, который является общедоступным классом из вашего проекта DAL. Какие участники есть в этом классе? Чтобы ответить на этот вопрос, нам нужно посмотреть не только на этот класс, но и на любые базовые классы. И вот так, БАМ, нам нужно знать о DbContext Entity Framework.

Все, что разоблачает является общедоступным типом структуры сущностей 1 из вашего DAL, может быть причиной того, что коду Api понадобится эта ссылка - это могут быть базовые классы или любые такие типы, используемые в качестве параметров или возвращаемых типов для любых других членов; или атрибуты.

Один из распространенных способов скрыть это - поместить какой-то тип фасада перед реальным контекстом и сделать только что (и ваши простые объекты) общедоступными из вашего DAL.


but the fact is that on top of all this is not enough as I also need to add this to the web.config:

Да, у «библиотек» нет файлов конфигурации времени выполнения, есть только у приложений. У приложений, отличных от Asp.Net, есть свои файлы <exename>.exe.config, у приложений ASP.Net есть web.config (в новых версиях ASP.Net расширены возможные источники конфигурации). Любые параметры конфигурации среды выполнения должны находиться в файле что2. К сожалению, некоторые инструменты Visual Studio добавят файл app.config в библиотеки, из-за чего создается впечатление, что эти библиотеки имеют отдельную конфигурацию. Я рассматриваю это как ошибку в инструментарии, другие могут щедро описать это как предоставление вам примера настроек конфигурации, которые необходимо поместить в файл конфигурации приложения.


1 Используется в широком смысле слова «внешний код видит это». Это, конечно, не только public, но и protected

2 На самом деле может быть несколько файлов web.config на нескольких уровнях, но обычно вы хотите, чтобы основная конфигурация находилась в одном из базовых каталогов приложения. Кроме того, вы можете ссылаться на другие файлы конфигурации, чтобы они содержали части вашей конфигурации, но они предназначены для того, чтобы иметь возможность сказать «весь этот раздел конфигурации находится в файле это», а не «посмотрите на этот другой файл конфигурации и« объедините »его содержимое с текущий файл "

Большое спасибо за помощь @Damien_The_Unbeliever. Пожалуйста, посмотрите мою правку. Я переписал код и теперь думаю, что частично решил свою проблему, но получаю другую ошибку.

Diego Perez 09.10.2018 11:15

@DiegoPerez - я уже пытался осветить это во второй части своего ответа. Ваш DAL не имеют файл конфигурации, несмотря на то, что какие-либо инструменты VS могли ввести вас в заблуждение (или вы явно добавили его). Конфигурация должна быть в web.config.

Damien_The_Unbeliever 09.10.2018 11:21

О да, вы сделали это очень хорошо, извините, теперь - хотя я отказываюсь - я начинаю верить, что вам определенно нужно поместить все конфигурации данных и ссылки в свой пользовательский интерфейс, хотя для этого у вас есть DAL :(

Diego Perez 09.10.2018 11:25

@DiegoPerez - вам не нужна ссылка как таковая, если все, что вы делаете, это помещаете материал, упоминающий его в в конфигурации, который будет использоваться во время выполнения. Конечно, вам нужно, чтобы сами библиотеки DLL присутствовали в каталоге bin, потому что от них зависит ваш DAL.

Damien_The_Unbeliever 09.10.2018 11:28

Еще раз спасибо @Damien_The_Unbeliever, вы очень любезны. Учитывая это, я предполагаю, что в моем DAL мне не нужно будет устанавливать пакеты Oracle через Nuget (Oracle.ManagedDataAccess и Oracle.ManagedDataAccess.EntityFramework), поскольку они уже установлены в проекте Web Api и нуждаются только в пакете Entity Framework, или я неправильный?

Diego Perez 09.10.2018 11:32

Хорошо, @Damien_The_Unbeliever уже тестировал себя и могу подтвердить, что если вы устанавливаете пакеты Oracle в пользовательском интерфейсе, они вам не нужны в DAL. Я удалил их, и приложение продолжает работать. Я отмечу ваш ответ как правильный, потому что он был полезен для меня, и я ценю ваши усилия, хотя я не могу поверить, что вам нужно сохранять конфигурацию данных на уровне пользовательского интерфейса.

Diego Perez 09.10.2018 13:22

Другие вопросы по теме