从实体到DTO(检索仅在DB上的信息)
本文关键字:DB 信息 实体 DTO 检索 | 更新日期: 2023-09-27 18:10:55
我有域类(说EventoSottomissione
)与一些信息。然后我有DTO(说EventoSottomissioneDTO
)具有相同的信息和与持久性相关的东西(即EventoSottomissione
和EventoSottomissioneDTO
都具有EventCode
属性,但只有EventoSottomissioneDTO
具有IdEvent
属性)。
现在假设我有一个方法Delete
,将从数据库中删除一些事件。这个方法是从我的领域层调用的,因此,这忽略了持久层和DTO,因此Delete
将采用EventoSottomissione
的IEnumerable
。DbSet
确实要取EventoSottomissioneDTO
的IEnumerable
。
所以,在Delete
方法中要做的第一件事是"转换"IEnumerable<EventoSottomissione>
在IEnumerable<EventoSottomissioneDTO
>,但我不能简单地使用AutoMapper(例如:如何填充IdEvent
属性-此信息仅在DB上)
我的Delete方法是这样的
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;
}
这是工作,但我发现这个解决方案真的很可怕。我怎样才能以更优雅的方式做每件事?
首先,dto与EF层(持久化)有什么关系?dto通常是域实体的投影,使它们更"可序列化",并消除与持久层相关的"噪声"(例如,导航属性,它可能导致循环序列化问题),不应该被安全性或其他应用程序逻辑暴露的属性,等等)。
要回答你的问题,我们必须了解移除的收入参数是什么?从你的代码中,我假设你正在删除所有具有EventCode
的实体,实际上是在listOfCodes
.
想象一下使用你当前API的人:应该在类型T的对象中填充什么属性?T型到底是什么?删除过滤逻辑会使用与PK无关的属性(我想是IdEvent
)吗?返回bool是什么意思?是说所有东西都被删除了还是别的什么?它能打碎任何人的大脑,对吧?
那么,您想通过IdEvent
删除还是想坚持当前逻辑并删除listOfCodes
中出现的具有EventCode
的所有实体?如果你想通过EventCode
删除,那么当然,如果你不使用任何实体框架。扩展后,您必须通过listOfCodes
获得所有实体,然后删除所有这些实体,就像您已经完成的那样。只需传递更合适的参数,如IEnumerable<EventCodeType> eventCodes
,因为当前通用的IEnumerable<T> entities
对使用您的API的任何人都没有任何意义。此外,我将方法名称更改为DeleteByEventCodes
之类的东西。
或者你可以使用EntityFramework。使用.Delete(expression)
扩展和删除所需的实体。但是不要调用.SaveChanges()
,因为当你调用.Delete(expression)
时,这个库会调用JIT,这就是我不太喜欢它的原因,因为它打破了EF的一些设计概念。
所以主要的想法是重新设计当前的API:将方法名称和传入参数更改为更合适的名称。然后你的代码将更容易理解和使用。