从实体到DTO(检索仅在数据库上的信息)

时间:2014-07-01 15:22:39

标签: c# entity-framework entity dto

我有域类(说EventoSottomissione),但有一些信息。然后我的DTO(说EventoSottomissioneDTO)具有相同的信息和与持久性相关的内容(即EventoSottomissioneEventoSottomissioneDTO都有EventCode属性,但只有EventoSottomissioneDTO } IdEvent属性。

现在假设我有一个方法Delete,它将从数据库中删除一些事件。这个方法是从我的域层调用的,因此,这对于持久层和DTO一无所知,因此DeleteIEnumerable EventoSottomissioneDbSet确实必须IEnumerable EventoSottomissioneDTO

因此,方法Delete要做的第一件事就是“转换”IEnumerable<EventoSottomissione>中的IEnumerable<EventoSottomissioneDTO&gt;但我不能简单地使用AutoMapper(例如:如何填充IdEvent属性 - 此信息仅在DB上)

所以我的删除方法是这样的:

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;
}

这样做,但我发现这个解决方案真的很可怕。我怎样才能以更优雅的方式做所有事情?

1 个答案:

答案 0 :(得分:1)

首先,DTO如何与EF层(持久性)相关? DTO通常是域实体的投影,以使它们更具有可序列化的特征。并消除&#34;噪音&#34;与持久层有关(例如导航属性,可导致循环序列化问题),不应由安全性或其他应用程序逻辑公开的属性等。
要回答你的问题,我们必须了解删除的收入参数是什么?在您的代码中,我假设您要移除EventCode中实际位于listOfCodes的所有实体。
想象一下使用您当前API的人:应该使用哪些属性是否填充了T类型的对象? T实际上是什么类型的?在删除过滤逻辑中是否会使用与PK无关的属性(我认为IdEvent)?返回bool是什么意思?这是否意味着一切都被删除或只是一些东西?它可以打破任何大脑,对吗?左,你想要按IdEvent删除,还是想坚持当前逻辑并删除EventCode中出现listOfCodes的所有实体{1}}?如果您想要EventCode删除,那么当然如果您不使用任何EntityFramework.Extended,则必须通过listOfCodes获取所有实体,然后删除所有这些实体像你这样的实体已经完成了。只需传递更合适的参数,例如IEnumerable<EventCodeType> eventCodes,因为当前的通用IEnumerable<T> entities对使用您的API的任何人都没有任何意义。我还要将方法名称更改为DeleteByEventCodes之类的名称。
或者您可以使用EntityFramework.Extended并使用.Delete(expression)删除所需的实体。但请不要拨打.SaveChanges(),因为这个图书馆会在您拨打.Delete(expression)时拨打JIT,这就是为什么我不喜欢它,因为它打破了一些EF设计理念。
所以主要的想法是重新设计您当前的API:将方法名称和传入参数更改为更合适的API。然后您的代码将更容易理解和使用。