Sto cercando di capire come funziona questo problema, dove sto utilizzando Entity Framework (6) in un'applicazione N-tier. Poiché i dati del repository (che contiene tutte le comunicazioni con il database) dovrebbero essere utilizzati in un livello superiore (l'interfaccia utente, i servizi, ecc.), Ho bisogno di associarlo a DTO.
Nel database ci sono molte relazioni molti-a-molti in corso, quindi la struttura dati può / diventerà complessa da qualche parte lungo la linea della vita delle applicazioni. Quello su cui mi sono imbattuto è che sto ripetendo esattamente lo stesso codice durante la scrittura dei metodi del repository. Un esempio di questo è il mio FirmRepository
che contiene un metodo GetAll()
e il metodo GetById(int firmId)
.
Nel GetById(int firmId)
, ho il seguente codice (incompleto poiché ci sono molte più relazioni che devono essere mappate su DTO):
public DTO.Firm GetById(int id)
{
// Return result
var result = new DTO.Firm();
try
{
// Database connection
using (var ctx = new MyEntities())
{
// Get the firm from the database
var firm = (from f in ctx.Firms
where f.ID == id
select f).FirstOrDefault();
// If a firm was found, start mapping to DTO object
if (firm != null)
{
result.Address = firm.Address;
result.Address2 = firm.Address2;
result.VAT = firm.VAT;
result.Email = firm.Email;
// Map Zipcode and City
result.City = new DTO.City()
{
CityName = firm.City.City1,
ZipCode = firm.City.ZipCode
};
// Map ISO code and country
result.Country = new DTO.Country()
{
CountryName = firm.Country.Country1,
ISO = firm.Country.ISO
};
// Check if this firm has any exclusive parameters
if (firm.ExclusiveParameterType_Product_Firm.Any())
{
var exclusiveParamsList = new List<DTO.ExclusiveParameterType>();
// Map Exclusive parameter types
foreach (var param in firm.ExclusiveParameterType_Product_Firm)
{
// Check if the exclusive parameter type isn't null before proceeding
if (param.ExclusiveParameterType != null)
{
// Create a new exclusive parameter type DTO
var exclusiveParameter = new DTO.ExclusiveParameterType()
{
ID = param.ExclusiveParameterType.ID,
Description = param.ExclusiveParameterType.Description,
Name = param.ExclusiveParameterType.Name
};
// Add the new DTO to the list
exclusiveParamsList.Add(exclusiveParameter);
}
}
// A lot more objects to map....
// Set the list on the result object
result.ExclusiveParameterTypes = exclusiveParamsList;
}
}
}
// Return DTO
return result;
}
catch (Exception e)
{
// Log exception
Logging.Instance.Error(e);
// Simply return null
return null;
}
}
Questo è solo un metodo. Il metodo GetAll()
avrà quindi la stessa logica di mappatura che si traduce in codice duplicato. Inoltre, quando vengono aggiunti altri metodi, ad esempio un metodo Find
o Search
, è necessario copiare nuovamente la stessa mappatura. Questo, ovviamente, non è l'ideale.
Ho letto molto sul famoso framework AutoMapper che può mappare le entrate da / verso DTO, ma dal momento che ho queste relazioni molti-a-molti si sente rapidamente gonfio con il codice di configurazione di AutoMapper. Ho letto anche questo articolo, che ha senso ai miei occhi: http://rogeralsing.com/2013/12/01/why-mapping-dtos-to-entities-using-automapper-and-entityframework-is-horrible /
C'è un altro modo per farlo senza copiare / incollare lo stesso codice più e più volte?
Grazie in anticipo!
È possibile creare un metodo di estensione su Entity Firm (DB.Firm) come questo,
public static class Extensions
{
public static DTO.Firm ToDto(this DB.Firm firm)
{
var result = new DTO.Firm();
result.Address = firm.Address;
result.Address2 = firm.Address2;
//...
return result;
}
}
Quindi puoi convertire l'oggetto DB.Firm in qualsiasi punto del tuo codice come firm.ToDto();