遵循DRY原则的业务规则验证



Background -我通常在实体类本身的属性级别执行验证,要么使用DataAnnotation属性,要么通过实现IValidatableObject接口。此代码通常不能访问DBContext

然后,我通常将更复杂的业务规则验证放在服务层。这类验证的示例有:检查一个值在数据库中是否唯一,以及检查其他实体值。这些类确实需要DBContext来查询数据库。

Issue -我的问题是我最终在服务层重复相同的代码。例如,当我插入和更新一个实体时,我重复相同的代码来检查给定的值是否唯一。

我读了关于设计模式的书,如约束、策略和规范。我想我只是需要一点帮助,把它们放在一个EF的、分层的上下文中。感谢。

我将保持实体级别的验证。在这里,您可以检查是否设置了所需的属性,它们的值是否正确,您还可以比较实体上的属性。这确保了实体(与其他实体无关)处于有效状态。

在Service层,您可以通过调用validate方法来验证传递到方法中的任何实体,您还可以与数据库中的实体进行比较。

在验证ID是否唯一的实例中,您可以在您的存储库中添加一个名为GetById的方法,通过该方法您可以传递您想要检查的实体的ID,如果它返回NULL,那么您没有找到具有该ID的实体,因此它是唯一的。

例如:

public class MyRepository
{
  public MyEntity GetById(int id)
  {
    return _entitySet.FirstOrDefault( item => item.Id == id );
  }
}
public class MyService
{
  public void ServiceMethod(Entity entity)
  {
    if( _repository.GetById( entity.Id ) == null)
    {
      // entity.Id is unique!
    }
    else
    {
      // entity.Id is not unique!
    }
  }
}

您的每个存储库都可以访问其管理的实体,例如实体框架中的ObjectSet(我认为它是这样称呼的),因此您可以安全地将任何共享验证放在存储库上,在特定实体的上下文中。

例如:

public class MyRespository
{
    public bool IsIdUnique(int id)
    {
      Entity entity = _entitySet.FirstOrDefault( item => item.Id == id );
      return entity == null ? true : false;
    }
}
public class MyService
{
  public void ServiceMethod(Entity entity)
  {
    if( _repository.IsIdUnqiue(entity.Id) )
    {
      // entity.Id is unique!
    }
    else
    {
      // entity.Id is not unique!
    }
  }
}

你也可以将GetById添加到上面的MyService类中,并让IsIdUnique方法调用它,而不是重新键入lambda。这样您就可以重用GetById逻辑。

当你必须访问数据库时,你需要使用DbContext,而DbContext有一个名为ValidateEntity的可重写方法。参见本文:实体框架验证。

我把我使用的代码放在这里的另一个答案

谢谢你的回答,他们非常有见地。我认为这篇文章很好地回答了我的问题。感谢。

http://msdn.microsoft.com/en-us/data/gg193959.aspx

最新更新