.Net Web Api: Почему я должен установить Entity Framework на мой проект контроллеров Web Api? - PullRequest
0 голосов
/ 09 октября 2018

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

Длячто я настроил Data Access Layer с 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контроллер У меня есть метод post:

[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 должен быть установлен.

Дело в том, что с интуитивной точки зрения (и теоретически) у вас нет никаких причин устанавливать какие-либо элементы данных в проект пользовательского интерфейса (или 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, и таквы начинаете иметь свой пользовательский интерфейс (или веб-интерфейс), полный ссылок на связанные с данными вещи.

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

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

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

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

Любые идеи о том, как обойти это?

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

Спасибо.

Редактировать: Небольшой переписанный код.

Я переписал некоторый код, и теперь я создал VacancyRКласс Epository в DAL выглядит следующим образом:

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 и вызвал метод add в контроллере, как этот:

[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, когда в моем DAL app.config ясно, что всессылки на Oracle, а не одна ссылка на Sql Server?2) Почему возникает ошибка «Создать базу данных» при попытке добавить запись в существующую таблицу?

1 Ответ

0 голосов
/ 09 октября 2018

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

Ваш код API, очевидно, знает о WFRHEntities, который является открытым классом из вашего проекта DAL.Какие члены этого класса?Чтобы ответить на этот вопрос, нам нужно взглянуть не только на этот класс, но и на любые базовые классы.И точно так же, BAM, нам нужно знать о DbContext.

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

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


но на самом деле этого недостаточно, так как мне нужно добавить это в web.config:

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


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

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

...