我的 Web API Rest 客户端迫使我引用实体框架

本文关键字:引用 实体 框架 Web API Rest 客户端 我的 | 更新日期: 2023-09-27 18:30:15

我有一个MVC Api端点,我正在创建一个包装api端点服务的api rest客户端项目。

我正在使用实体框架,首先是代码。

我的 Web api 项目如下所示:

project-mvc
project-core  (this contains entity framework, models, etc.)

现在,当我创建我的 rest api 客户端项目时:

project-api-client

问题是,我必须引用项目核心,因为它包含模型,但随后我也得到了实体框架,因为它是一个依赖项。

所以我尝试创建一个单独的模型项目:

project-models

但似乎它仍然必须引用实体框架,否则我的属性似乎不起作用,例如:

public class Something
{
        [Key]
        [Column("Something_ID")]
        public int Id { get; set; }
    ....
}

我以为你需要的只是使用System.ComponentModel.DataAnnotations,但我被迫引入了EntityFramwork。

我做错了吗?

我的 Web API Rest 客户端迫使我引用实体框架

听起来你需要

解耦你的层;一般来说,传递 EF 对象,更具体地说,将它们从控制器扔到网络上是一个坏主意,因为您最终可能会公开客户没有兴趣(或业务)知道的数据模型部分。

纠正此问题的一种方法如下(注意:此示例是即时完成的,严格来说不是"最佳"或最解耦的正确方法,但我想朝着正确的方向推动您

接口您需要做的是定义一个接口,用于描述客户端可能希望看到的 MyThing 的重要属性。将此接口定义放在单独的项目(假设为"MyInterfaces")中,并从 EF 项目中引用此项目:

public interface IThing
{
   int ID{get;set;}
   string Data{get;set;}
}

数据传输对象当你在它的时候,在接口项目中创建一个具体的实现 IThing 的数据传输对象:

public class MyThingDTO:IThing
{
   public int ID{get;set;}
   public string Data{get;set;}
}

注意:严格来说,这个模型应该在项目的各个"层"中重新实现,接口项目应该只包含接口,但为了简单起见,我在所有层中使用相同的 DTO。

实体现在,您可以在 EF 项目中定义如下所示的实体

public class MyThing:IThing
{
   [Key]
   [Column("MyThing_ID")
   public int ID{get;set;}
   [Column("MyThing_Data")
   public string Data {Get;set;}
}

数据访问层现在,您可以创建一个引用实体框架和接口项目的数据访问层项目,并创建某种类,其工作是为 IThings 的请求提供服务

public class MyThingDataService
{
   public IThing GetByID(int ID)
   {
      //EF code to query your database goes here, assuming you have a valid DBContext called "ctx". I won't go into how you might create or inject this, etc, as it's a separate topic e.g Dependency Injection.
     var thing = ctx.MyThings.FirstOrDefault();
     if (thing!=null)
    {
        return new MyThingDTO{ID=thing.ID, Data=thing.Data};
    }
    else{//handle the not found case here}
   }
}

引用最后,从 MVC 项目引用数据访问层和接口项目,控制器代码现在如下所示

public MyThing Get(int id)
{
   //assuming you have an instance of MyThingDataService here, injected via DI or manually created, etc.
//strictly speaking we should declare our controller return type as IMyThing 
//but this means we have to also decorate the DTO class with some attributes for the serialiser     
//(KnownType) and I don't want to confuse things, hence the cast.
   return dataService.GetByID(id) as MyThing; 
}

现在,对 EF 项目的唯一引用是在中央接口项目中。

您的客户端项目

只需要引用接口项目(实际上您实际上并不需要这样做,因为您的客户端通过 HTTP 接收序列化数据,因此可以自由地在 IMyThing 接口上实现自己的版本,但为了节省时间而重用它很方便)。

总结

我提到这只是朝着正确方向的推动 - 要实现真正的解耦实现,您需要做更多的工作。 - 您的数据访问层也应由接口定义,并且您应该使用某种 DI 容器将其注入 MVC 控制器; - 您的接口项目应该只包含接口,并且每一层都应该实现自己的具体类来表示流经它的数据(即它们都应该有自己的MyThingDTO实现IMyThing的风格) - 当你这样做时,你会看到你有一个很好的解耦系统,因为没有一个层(MVC,数据访问,EF)彼此有任何引用,只有集中式接口项目。 - 可能比我聪明的人会发现你需要做的其他事情,因为我可能忘记了一些事情 - 这里很早(晚了?

无论如何。希望这有帮助。