Reputation: 5056
I have domain class (says EventoSottomissione
) with some informations. Then I've DTO (says EventoSottomissioneDTO
) with the same informatiosn and something related to persistence (i.e. both EventoSottomissione
and EventoSottomissioneDTO
has EventCode
property, but only EventoSottomissioneDTO
has IdEvent
property).
Now suppose I have a method Delete
that will remove some events from the database. This method is called from my domain layer and so, this is ignorant about persistence layer and DTO, thus Delete
will take an IEnumerable
of EventoSottomissione
. DbSet
indeed have to take a IEnumerable
of EventoSottomissioneDTO
.
So, the first thing to do in method Delete
is to "convert" the IEnumerable<EventoSottomissione>
in IEnumerable<EventoSottomissioneDTO
> but I can't do this simply using AutoMapper (for instance: how to fill IdEvent
properties - this information is only on the DB)
So my Delete method is something like that:
public bool Delete(IEnumerable<T> entities) // typeof(T) is EventoSottomissione
{
// get all eventCode from entities collection
var listOfCodes = (from p in entities.Cast<EventoSottomissione>().ToList<EventoSottomissione>()
select p.EventCode).Distinct();
// using the list of eventCode I can create list EventoSottomissioneDTO (with even IdEvent)
IEnumerable<EventoSottomissioneDTO> listOfDto = (from _db in Context.CatalogoEventi
where listOfCodes.Contains(_db.EventCode)
select _db).ToList<EventoSottomissioneDTO>();
DbSet.RemoveRange(listOfDto);
return Context.SaveChanges() > 0;
}
This do the job, but I find this solution really scary. How can I do everything in a more elegant manner?
Upvotes: 0
Views: 393
Reputation: 511
First of all, how DTOs are related to EF layer (persistence)? DTOs are usually projection of domain entities, to make them more "serializable" and to remove "noise" related to persistence layer (e.g. navigation properties, which can cause cyclic serialization problem), properties that should not exposed by security or other application logic, etc.).
To answer your question we have to understand what is the income parameters for removing? From your code I've made assumption that you are removing all the entities that has EventCode
that is actually in listOfCodes
.
Just imagine someone who uses your current API: what properties should be populated in objects of type T? What type T actually is? Will properties that are not related to PK (IdEvent
I think) be used in delete filtering logic? What does returned bool mean? Does it mean that everything was deleted or just something? It can break any brain, right?
So do you want to delete by IdEvent
or do you want to stick to the current logic and delete all the entities that has EventCode
that appears in listOfCodes
? If you want to delete by EventCode
then of course if you don't use any EntityFramework.Extended you'll have to get all the entities by listOfCodes
and then remove all those entities like you have already done. Just pass in more appropriate parameter, something like IEnumerable<EventCodeType> eventCodes
, because current generic IEnumerable<T> entities
doesn't make any sense for anyone who will use your API. Also I'd change method name to something like DeleteByEventCodes
.
Or you can use EntityFramework.Extended and delete needed entities using .Delete(expression)
. But don't call .SaveChanges()
because this library makes call JIT when you call the .Delete(expression)
, that's why I don't like it too much, because it breaks some of EF design concepts.
So main idea is to redesign your current API: change method name and incoming parameter to more suitable one. Then your code will be much easier to understand and to use.
Upvotes: 1