2017-08-30 51 views
1

對不起,關於標題,我找不出合適的描述。C#n層實體變更未在插入後反映在DTO中

我有四個層次:

  • 核心層:包含DTO的,服務和存儲庫接口。
  • 業務層:包含處理業務邏輯的「服務」。
  • 數據訪問層:包含處理數據庫訪問和將實體轉換爲DTO的存儲庫。
  • 表示層:UI東西

我碰到的,我不知道怎麼解決最好的問題。我異步增加一個實體到數據庫中,像這樣:

// The AdministrationRate has an ID property, Entity Framework does treat the property as an Identity and does increment it. 
var adminRate = new AdministrationRate() {FosterChildID = fosterChild.ID}; 
await adminRateService.AddAdministrationRate(adminRate); 

AdministrationRateService:

public async Task AddAdministrationRate(AdministrationRate administrationRate) => await repo.AddAdministrationRate(administrationRate); 

AdministrationRateRepository:

//I use a generic repository to avoid code repition. 
//Notice the DTO to entity conversion. ID is not set in the conversion. 
public async Task AddAdministrationRate(AdministrationRate administrationRate) => await Add(administrationRate.ToEntity()); 

庫:

public async Task Add(TEntity entity) 
{ 
    using (var db = new DatabaseContext()) 
    { 
     db.Entry(entity).State = EntityState.Added; 
     await db.SaveChangesAsync(); 
    } 
} 

而且這是行得通的,問題是在它被添加之後,新生成的實體ID沒有被反映在DTO(DTO.ID = 0)中。

我不可能返回更新的實體,因爲它會要求我將實體轉換爲我的表示層中的DTO,以保持它一直是異步的。

由於通用存儲庫,我也不能只返回ID。

我真的不想擺脫通用的存儲庫,因爲它是非常有用的,但我真的不能看到另一種方法來安全地做到這一點,而不改變數據庫(我不能這樣做)。

那麼,我該怎麼辦?

回答

0

回答: 我發現了兩個解決這個問題的方法,後者就是我實際使用的方法。


解決方案1:

我想通了,我可以讓Add方法返回一個實體的ID,通過標記的通用庫虛擬的Add方法,然後重寫它的一個特定的存儲庫並最終從調用代碼中捕獲結果。這當然意味着更多的代碼,但也不會將我從實體轉換到DTO的錯誤層(不是那是一個選項)。


解決方案2:

顯然,await關鍵字異步返回任務的結果類型,而不是阻止它像result,所以我能夠轉換和從我的倉庫返回DTO:

AdministrationRateRepository:

public async Task<AdministrationRate> AddAdministrationRate(AdministrationRate administrationRate) => (await Add(administrationRate.ToEntity())).ToModel(); 

我想如果有人可以發表評論,我需要使我的ToEntity()ToModel()方法異步,以及如何完成。

編輯:哦,沒有發現有人張貼。我會看看你的建議Akos,謝謝。

0

這裏有幾個想法,我會嘗試。不知道他們中的任何一個是否適合您的需求,但可能會讓您開始(或至少開始討論:)):

1;爲您的DTO引入一個接口,如IDto。然後,您可以更改通用存儲庫以返回Task<IDto>而不是任務。在Add方法中將實體轉換爲具體的Dto,通過IDto引用返回,然後將其轉換回服務中。

2;如果您有一個類似IRepository<TEntity>Repository<TEntity>的通用存儲庫,那麼您可以嘗試向通用存儲庫引入另一個參數並將其設置爲IRepository<TEntity,TDto>。通過這種方式,您可以保留體系結構的一般特性,但也可以從Add方法返回Task<Dto>

3;你可以走得更遠:創建一個IDto<TEntity>界面。然後你可以有一個User實體和一個UserDto:IDto<User>。然後,您可以將Add方法的返回類型更改爲Task<IDto<TEntity>>。或者,再次使用雙參數存儲庫IRepository<TEntity,TDto>並添加約束,以便TDto必須實現IDto<TEntity>