[英]My Web Api Rest client is forcing me to reference Entity Framework
我有一個MVC Api端點,並且我也在創建一個api rest客戶端項目,該項目還包裝了api端點服務。
我正在使用實體框架,首先進行編碼。
我的Web API項目如下所示:
project-mvc
project-core (this contains entity framework, models, etc.)
現在,當我創建我的rest api客戶端項目時:
project-api-client
問題是,我必須引用項目核心,因為它包含模型,但是由於它是依賴項,因此我還獲得了實體框架。
因此,我嘗試創建一個單獨的模型項目:
project-models
但是似乎仍然必須引用EntityFramework,否則我的屬性似乎不起作用,例如:
public class Something
{
[Key]
[Column("Something_ID")]
public int Id { get; set; }
....
}
我以為您所需要的只是使用System.ComponentModel.DataAnnotations,但我被迫引入EntityFramwork。
我做錯了嗎?
聽起來您需要解耦圖層; 通常,將EF對象傳遞到周圍,更具體地說,是將它們從控制器通過電線扔掉是一個壞主意,因為您最終可能會暴露出數據模型中客戶不感興趣(或不感興趣)的部分。
糾正此問題的一種方法如下(注意:此示例是即時進行的,並不是嚴格地說是“最佳”或最不相關的正確方法,但我想向您推薦正確的方向 )
接口您需要做的是定義一個接口,該接口描述客戶端可能希望看到的MyThing的重要屬性。 您可以將此接口定義放在一個單獨的項目中(假設為“ MyInterfaces”),並從您的EF項目中引用該項目:
public interface IThing
{
int ID{get;set;}
string Data{get;set;}
}
使用數據傳輸對象時,可以在Interfaces項目中創建IThing的具體實現數據傳輸對象:
public class MyThingDTO:IThing
{
public int ID{get;set;}
public string Data{get;set;}
}
注意:嚴格來說,應在項目的各個“層”中重新實現此模型,而interfaces項目應僅包含接口,但為簡單起見,我在所有層中都使用相同的DTO。
實體現在您可以在EF項目中定義一個實體,如下所示
public class MyThing:IThing
{
[Key]
[Column("MyThing_ID")
public int ID{get;set;}
[Column("MyThing_Data")
public string Data {Get;set;}
}
數據訪問層現在,您可以創建一個數據訪問層項目,該項目引用您的Entity Framework和Interface項目,並創建某種類,該類的工作是為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項目的唯一引用是在Central Interfaces項目中。
您的客戶端項目僅需要引用Interfaces項目(實際上,您實際上並不需要這樣做,因為您的客戶端通過HTTP接收序列化數據,因此可以自由地在IMyThing接口上實現自己的功能,但是重新進行操作非常方便僅用於節省時間)。
包起來
我提到這只是朝正確方向的推動力-要實現真正分離的實現,您需要做更多的工作。 -您的數據訪問層也應按接口定義,並且應使用某種DI容器將其注入到MVC控制器中; -您的Interfaces項目應該只包含接口,並且每一層都應實現自己的具體類以表示流經它的數據(即,它們都應具有自己的MyThingDTO實現IMyThing的風格)-執行此操作時,您將看到一個很好解耦的系統,因為所有層(MVC,數據訪問,EF)都沒有相互引用,而僅涉及集中式接口項目。 -也許比我聰明的人會發現您需要做的其他事情,因為我可能已經忘記了一些-現在還很早(遲到嗎?)。
無論如何。 希望這可以幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.