我有域类(说EventoSottomissione
),但有一些信息。然后我的DTO(说EventoSottomissioneDTO
)具有相同的信息和与持久性相关的内容(即EventoSottomissione
和EventoSottomissioneDTO
都有EventCode
属性,但只有EventoSottomissioneDTO
} IdEvent
属性。
现在假设我有一个方法Delete
,它将从数据库中删除一些事件。这个方法是从我的域层调用的,因此,这对于持久层和DTO一无所知,因此Delete
将IEnumerable
EventoSottomissione
。 DbSet
确实必须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;
}
这样做,但我发现这个解决方案真的很可怕。我怎样才能以更优雅的方式做所有事情?
答案 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。然后您的代码将更容易理解和使用。