2011-06-02 94 views
2

在當前的項目中,我們決定使用dto來在服務器和客戶端之間傳輸數據。更清晰的方法來編寫解析DTO的代碼

Dto's是平坦的,奉承不是問題,它可以做到沒有太多麻煩。但是不贊成實現可能會變得非常困難,因爲用戶可能會刪除,創建和更新扁平實體圖的某些部分。

因此,這是示例代碼的Web服務方法之一:

[Update, EmpresaHasPermissions("PERMIT_INS_Employee")] 
    public void UpdateBackground(EmployeeBackgroundDTO dto) 
    { 
     using (var context = GetObjectContext()) 
     { 
      var user = EmpresaAuthentication.Current.User; 

      Employee employee = context.Employees 
       .Include(it => it.Nationality) 
       .Include(it => it.EthnicOrigin) 
       .Include(it => it.MaritalStatus) 
       .Include(it => it.Religion) 
       .Include(it => it.CRB) 
       .Include(it => it.Passport) 
       .Single(it => it.OwnerOrganizationId == user.OrganizationId && 
           !it.Deleted && it.Id == dto.Id); 

      var updater = new EmployeeBackgroundUpdater(context); 

      updater.UpdateEntity(employee, dto); 

      context.SaveChanges(); 

      dto.MaritalStatusId = employee.MaritalStatusId; 
      dto.EthnicOriginId = employee.EthnicOriginId; 
      dto.ReligionId = employee.ReligionId; 
     } 
    } 

正如你可以看到這裏有混合了很多東西: 上下文創建 數據選擇 調用數據更新 發送新的ID創建DTO是返回給客戶端

事情開始,當你看到EmployeeBackgroundUpdater是如何實現的是越來越值得:

public override void UpdateEntity(Employee employee, EmployeeBackgroundDTO dto) 
{ 
    employee.InjectFrom(dto); 

    if (!IsPassportNull(dto)) 
    { 
     if (employee.Passport == null) 
     { 
      employee.Passport = new Passport(); 
     } 

     employee.Passport.IssueDate = dto.PassportIssueDate.Value; 
     employee.Passport.ExpiryDate = dto.PassportExpiryDate.Value; 
     employee.Passport.PassportNo = dto.PassportPassportNo; 
     employee.Passport.IssuingCountryId = dto.PassportIssuingCountryId.Value; 
     employee.Passport.OwnerUserId = UserId; 
    } 
    else 
    { 
     if (employee.Passport != null) 
     { 
      DeleteObject(employee.Passport); 
      employee.Passport = null; 
     } 
    } 

    if (!IsCRBNull(dto)) 
    { 
     if (employee.CRB == null) 
     { 
      employee.CRB = new CRB(); 
     } 

     employee.CRB.IssueDate = dto.CRBIssueDate.Value; 
     employee.CRB.ExpiryDate = dto.CRBExpiryDate.Value; 
     employee.CRB.Registration = dto.CRBRegistration; 
     employee.CRB.Notes = dto.CRBNotes; 
    } 
    else 
    { 
     if (employee.CRB != null) 
     { 
      DeleteObject(employee.CRB); 
      employee.CRB = null; 
     } 
    } 

    var epmpresaContext = (EmpresaEntities)ObjectContext; 

    AddMaritalStatus(employee, dto, epmpresaContext); 

    AddReligion(employee, dto, epmpresaContext); 

    AddEthnicOrigin(employee, dto, epmpresaContext); 

    employee.NationalityId = dto.NationalityId; 
} 

private void AddMaritalStatus(Employee employee, EmployeeBackgroundDTO dto, EmpresaEntities epmpresaContext) 
{ 
    if (!dto.MaritalStatusId.HasValue && !String.IsNullOrWhiteSpace(dto.MaritalStatusDescription)) 
    { 
     var item = epmpresaContext.MaritalStatuses.FirstOrDefault(
      it => it.Description.ToUpper() == dto.MaritalStatusDescription.ToUpper()); 

     if (item == null) 
     { 
      employee.MaritalStatus = new MaritalStatus 
      { 
       Description = dto.MaritalStatusDescription 
      }; 
     } 
     else 
     { 
      employee.MaritalStatus = item; 
     } 
    } 
    else 
    { 
     employee.MaritalStatusId = dto.MaritalStatusId; 
    } 
} 

代碼在結構上是相同的,唯一的區別是實體集合和實體類型的類型。這很可怕,因爲如果我們選擇更新驗證邏輯或類似的東西,我將不得不在項目中的許多不同地方重寫相同的代碼。

感謝您閱讀這一點。並且我有一組問題:

1)如何將有子對象的平面dto的解析成有效的實體圖?

2)應該dto(或呈現模型可能)包含對象的層次?

3)如何擺脫重複的代碼?

回答

4

要解析實體到DTO,反之亦然,您可以檢查AutoMapper。 DTO可以是對象的層次結構(它不必變平)。我擔心你永遠不會迴避一些重複的代碼,因爲每個實體類型都是特殊的,你必須手動處理它 - 這是使用DTO的複雜性。

相關問題