2017-06-18 84 views
1

算目前我使用此代码:通用的方法在实体框架

opportunity.Contacts.Where(x => x.IsDeleted = false).IsNullOrEmpty() 

在每个实体检查,如果在实体(例如Opportunity)存在任何集合。

public bool Delete(int companyId, int opportunityId) 
{ 
    var opportunity = _opportunityRepository.FindOne(companyId: companyId, opportunityId: opportunityId).FirstOrDefault(); 

    if (!opportunity.Contacts.Where(x => x.IsDeleted = false).IsNullOrEmpty()) 
    { 
     throw new UserFriendlyException(ErrorMessages.UserFriendly.UnableToDeleteEntityHasRelatedData); 
    } 

    opportunity.IsDeleted = true; 
    _opportunityRepository.Edit(opportunity); 
    CurrentUnitOfWork.Commit(); 

    return true; 
} 

这种方法是重复的,耗时数百个地方。

我们如何使它成为一个通用的功能,可以检查实体类型和使用反射或另一种方式来检查其所有特性,这实现ICollection<T>和执行查询,以检查他们的计数?

[ForeignKey("DepartmentId")] 
public virtual ICollection<DepartmentLocation> DepartmentLocations { get; set; } 
[ForeignKey("DepartmentId")] 
public virtual ICollection<EmployeePosition> EmployeePositions { get; set; } 
+1

为什么不启用级联删除的关系? – haim770

+0

或者如果不需要级联,则禁用级联...删除级联的默认级别取决于所需的关系或可选... – grek40

回答

0

即使您确实想通过反射来解决集合来执行像这样的检查,我也不会推荐它。您正在查看的问题域看起来像要强制执行软删除的业务逻辑,基本上说“如果我的所有子项都被标记为已删除,我只能标记为已删除”。你会很快与试图通过反射来做到这一点面临的问题包括:

  • 巨片延迟加载
  • 复杂和缓慢的代码检查上删除每个对象。

懒惰的加载风险,并试图逃脱它将是我第一次警告龙。我会考虑利用存储库中的IQueryable,而不是返回一个域对象。从那里,你可以灵活地深入到你的模型,以确定是否一个对象有任何积极的孩子:

var activeState = _opportunityRepository.GetById(companyId, opportunityId) // return IQueryable<Opportunity> 
    .Select(o=> new {o.IsDeleted, HasActiveContact = o.Contacts.Any(c=> !c.IsDeleted)}) 
    .SingleOrDefault(); 

从那里你可以检查匿名性。类型。发送到服务器的查询在单次点击时性能方面应该保持最佳状态,代码是一个简单的可扩展结构,您可以轻松扩展,而不用担心延迟加载等问题。例如,如果要在将父项标记为已删除之前扩展有关哪些子项仍处于活动状态的消息,则可以将其展开为返回活动子项。