UI层是否应该能够将lambda表达式传递到服务层而不是调用特定方法?

Jas*_*son 10 .net c# linq architecture asp.net

我正在研究的ASP.NET项目有3层; UI,BLL和DAL.我想知道UI是否可以接受将lambda表达式传递给BLL,或者UI是否应该传递参数,而Service方法应该使用这些参数来构造lambda表达式?这是一个显示两个senarios的示例类.

public class JobService 
{
    IRepository<Job> _repository;

    public JobService(IRepository<Job> repository) 
    {
        _repository = repository;
    }

    public Job GetJob(int jobID)
    {
        return _repository.Get(x => x.JobID == jobID).FirstOrDefault();
    }

    public IEnumerable<Job> Get(Expression<Func<Job, bool>> predicate)
    {
        return _repository.Get(predicate);
    }
}
Run Code Online (Sandbox Code Playgroud)

对于上面的类,UI可以调用以下内容:

JobService jobService = new JobService(new Repository<Job>());
Job job = jobService.Get(x => x.JobID == 1).FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

还是应该只允许调用GetJob(int jobID)?

这是一个简单的例子,我的问题一般是,如果UI层能够将lambda表达式传递到服务层而不是调用特定的方法吗?

Pat*_*her 8

这是基于情况的判断.传递这样的谓词并不一定是错的.我认为它应该被认为是一种轻微的难闻的气味.

如果传入lambda表达式允许您将6个方法减少到1,那么这可能是一个很好的举措.另一方面,如果你可以轻松地传入一个简单类型,那么lambda语法就是一种不必要的复杂化.

在上面的例子中,不知道上下文,我的偏好是使用一个简单的整数参数.通常应该有一个基本方法,只需通过它的ID获取记录.也许还有一两种其他类似的方法可以通过您的应用程序重复使用.然后可能是一个采用lambda的通用方法.

您还应该考虑一些建议应该是一个规则:您没有任何方法在您的UI和业务层之间使用lambda指定的谓词.(并且有些人有理由相信,你的知识库甚至不应该有这样的方法!)我不相信这应该是一个铁腕的规则,但有充分的理由.它们之间的业务和数据层应该保持危险的查询不会发生.如果允许传入lambda,那么UI层中的初级开发人员很容易指定可能真正影响数据库的查询.(例如,他们会对非索引字段进行大量查询,和/或使用LINQ到对象对结果集进行过滤,而不会意识到效率低下.)

像许多其他良好实践一样,这在某种程度上取决于范围.在我最近的大型应用程序中,我没有将lambda语法从UI层传递到业​​务层.我的计划是在业务层投入大量资金,使其非常聪明.它具有简单类型所需的所有方法.实际上,它通常通过简单的域对象属性为您提供所需的内容,而根本没有参数.我的界面确保UI只能导致有效的查询发生,可能只是UI层中的次要LINQ到对象谓词.(甚至对于"搜索"页面也是如此.我的业务层接受具有约束可能性的标准对象,并确保有效的查询.)

现在,你说的是"层",而不是"层".所以这些都在同一个组件中?lambda的另一个缺点是它们(目前)难以序列化.如果你不得不将你的等级分开,你会后悔的.