简体   繁体   English

.Net Web Api:为什么要在Web Api控制器项目上安装Entity Framework?

[英].Net Web Api: Why should I install Entity Framework on my Web Api controllers project?

I have a multi-layer .Net Web Api project where (apart from the Web Api layer itself) I have a DAL which will do all database operations (I'm working with Oracle). 我有一个多层.Net Web Api项目,其中(除Web Api层本身之外)我有一个DAL,它将完成所有数据库操作(我正在使用Oracle)。

For that I've configured Data Access Layer with NuGet and added these next three packages: 为此,我使用NuGet配置了数据访问层,并添加了以下三个软件包:

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

And defined an entities class like the next: 并定义一个实体类,如下所示:

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());
    }

Then in my Web Api Vacancy controller I have a post method: 然后在我的Web Api Vacancy控制器中,我有一个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" };
}

And this method receives a post request from an Angular app form to create a new vacancy request but cannot make it to work as it complains Entity Framework have to be installed. 而且此方法从Angular应用程序表单接收到一个发布请求,以创建一个新的空缺请求,但是由于它抱怨必须安装Entity Framework而无法使其正常工作。

The point is that from an intuitive perspective (and in theory) you don't have any reason to install any data elements in UI (or Web Api) project, that is the reason you are supposed to have a DAL. 关键是,从直观的角度(从理论上来说),您没有任何理由要在UI(或Web Api)项目中安装任何数据元素,这就是您应该拥有DAL的原因。

Let's say I wouldn't mind to install Entity Framework (I'm using v6.0) in Web Api project but the fact is that on top of all this is not enough as I also need to add this to the web.config: 假设我不介意在Web Api项目中安装Entity Framework(我正在使用v6.0),但事实是,仅此而已还不够,因为我还需要将其添加到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>

And for that I also have to add the two Oracle packages mentioned above through NuGet so Entity Framework knows it'll work with Oracle and not SQL Server and this way you start having your UI (or Web Api) full of Data related things references. 为此,我还必须通过NuGet添加上面提到的两个Oracle软件包,以便Entity Framework知道它可以与Oracle一起使用,而不与SQL Server一起使用,这样您就可以开始让UI(或Web Api)充满数据相关内容引用。

I don't want (and I don't think it's a good idea) to have all this stuff anywhere but in the DAL and FYI I'm not working with Repositories and Unit Of Work patterns as I don't know them so I'm trying to keep things simple. 我不想(而且我也不认为这是个好主意)所有这些东西都放在任何地方,但是在DAL和FYI中,我不使用存储库和工作单元模式,因为我不了解它们,所以我正在努力使事情变得简单。

I was reading this next post: 我正在阅读下一篇文章:

Why do I have to reference EF in my UI project? 为什么我的UI项目中必须引用EF?

but wasn't able to get to a workaround (or a solid solution) to my problem. 但无法解决我的问题(或可靠的解决方案)。

Any ideas on how to work around this? 关于如何解决此问题的任何想法?

Is it really that difficult to abstract your UI from the Data layer completely? 从数据层完全抽象UI真的很困难吗?

Thanks. 谢谢。

Edit: Little code rewritten. 编辑:少许代码重写。

I have rewritten some code and now I've created a VacancyRepository class in DAL like this: 我已经重写了一些代码,现在我在DAL中创建了一个VacancyRepository类,如下所示:

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

        }

        public void Add(Vacancy entity) {

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

After that I removed EntityFramework (and Oracle related packages) from Web Api project and removed all Data settings in Web Api web.config and call add method in controller like this: 之后,我从Web Api项目中删除了EntityFramework(以及与Oracle相关的软件包),并删除了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" };
}

This is my DAL app.config 这是我的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>

And the error I'm now receiving when trying to do an add operation is the next: 下一个是我现在尝试执行添加操作时收到的错误:

System.Data.SqlClient.SqlException: Permission denied in creating database in master database so now my questions are: System.Data.SqlClient.SqlException:在主数据库中创建数据库时拒绝了权限,所以现在我的问题是:

1) Why is it throwing an SQl exception when in my DAL app.config is it clear that all references are to Oracle and not even one Sql Server reference? 1)为什么在我的DAL app.config中很清楚所有引用都是对Oracle甚至没有一个Sql Server引用时,它引发SQl异常? 2) Why a "Create Database" error when I'm trying to add a record to an existing table? 2)为什么在尝试向现有表中添加记录时出现“创建数据库”错误?

You need to install everything that the compiler will need to reference during compilation. 您需要安装编译器在编译期间需要引用的所有内容。

Your Api code apparently knows about WFRHEntities , which is a public class from your DAL project. 您的Api代码显然了解WFRHEntities ,这是DAL项目中的公共类。 What members does that class have? 该班有哪些成员? In order to answer that question, we need to look not only at that class but also at any base classes. 为了回答这个问题,我们不仅要看该类,还要看所有基类。 And, just like that, BAM, we need to know about Entity Framework's DbContext . 而且,就像BAM一样,我们需要了解Entity Framework的DbContext

Anything that exposes an entity framework type publicly 1 from your DAL would be a reason for the Api code to need that reference - that could be base classes, or any such types used as parameters or return types for any other members; 任何从DAL公开1 公开了一个实体框架型将是在API代码,需要一个参考一个原因-这可能是基类,或用作参数的任何这样的类型或任何其他构件返回类型; or attributes. 或属性。

One common way to hide this is to place some kind of façade type in front of the real context, and only make that (and your plain entities) public from your DAL. 隐藏此外观的一种常见方法是将某种外观类型放置在真实上下文的前面,并仅将 (和您的纯实体)从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: 但事实是,这还远远不够,因为我还需要将其添加到web.config中:

Yes, "libraries" don't have runtime config files, only applications do. 是的,“库”没有运行时配置文件,只有应用程序有。 Non Asp.Net applications have their <exename>.exe.config files, ASP.Net applications have web.config (Newer flavours of ASP.Net have expanded what configuration sources are possible). 非Asp.Net应用程序具有其<exename>.exe.config文件,ASP.Net应用程序具有web.config (较新版本的ASP.Net扩展了可能的配置源)。 Any runtime configuration settings need to go in that file 2 . 任何运行时配置设置都需要进入文件2 It's unfortunate that some Visual Studio tooling will add an app.config file to libraries that makes it look like those libraries have separate configuration. 不幸的是,某些Visual Studio工具会将app.config文件添加到库中,使它们看起来像那些库具有单独的配置。 I see it as a bug in the tooling, others might generously describe it as giving you an example of the configuration settings you need to place in the application config file. 我将其视为工具中的错误,其他人可能会慷慨地将其描述为您需要在应用程序配置文件中放置的配置设置示例。


1 Used in the broad sense of "external code sees this". 1广义上使用“外部代码看到此”。 Which of course is not just public but also protected 当然,哪一个不仅是public而且还protected

2 There can in fact be multiple web.config files at multiple levels but typically you want core configuration to be in the one at the base directory for the application. 2实际上,可以在多个级别上存在多个web.config文件,但是通常您希望核心配置位于应用程序基本目录的其中一个目录中。 Also, you can reference other config files to contain parts of your configuration, but that's designed to be able to say "this entire configuration section is found in this file", not "look at this other config file and 'merge' its contents with the current file" 此外,您可以引用其他配置文件以包含配置的某些部分,但这是为了能够说“在文件中找到了整个配置部分”,而不是“查看此其他配置文件并将其内容与”合并”当前文件”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM