【问题标题】:How to design a common class to accept a list and dbset如何设计一个通用类来接受一个列表和数据库集
【发布时间】:2017-07-12 21:59:06
【问题描述】:

我有一些业务逻辑供 api 和使用数据库存储数据的作业管理器使用。像这样简化:。

class BusinessLogic 
{
    public IEnumerable<Request> Requests {get;set;}

    public List<Requests> GetData()
    {
         return Requests.Where(r => r.StatusId == Constants.STATUS_NOT_PROCESSED_ID).ToList();
    }
}

class apiprocessor
{
    public void Process()
    {
        var requests = new List<Request>();

        BusinessLogic.Requests = requests;
        BusinessLogic.GetData();
    }
}

class dbprocessor
{
    private DbContext _db;

    public void Process()
    {
        //this sends the where clause to the db
        //var requests = _db.Requests.Where(r => r.StatusId == Constants.STATUS_NOT_PROCESSED_ID).ToList();

        BusinessLogic.Requests = _db.Requests;  //type DbSet<Request> Requests
        //this one doesnt
        BusinessLogic.GetData();
    }
}

这在功能上可行,但有一个问题。

如果我尝试使用 db 处理器中的 dbcontext 获取数据,mysql 服务器收到的结果查询是:

SELECT
`Extent1`.`RequestID`, 
`Extent1`.`RequestType`, 
`Extent1`.`StatusId`
FROM `Requests` AS `Extent1`
 WHERE (0 = `Extent1`.`StatusId`)

(注意 WHERE 子句)

当在上面的 BusinessLogic 类中运行相同的代码时,得到的查询是:

SELECT
`Extent1`.`RequestID`, 
`Extent1`.`RequestType`, 
`Extent1`.`StatusId`
FROM `Requests` AS `Extent1`

缺少 Where 子句,这意味着正在检索整个表,然后将 where 子句应用于内存中的数据

无论如何设计公共类,以便在使用 dbset 调用它时将 where 子句发送到 db?

编辑:需要明确的是,IQueryable 不是一个选项,因为 List 不会从它继承,这是 api 处理器使用的。但是,在 api 处理器中使用 List 不是强制性的

谢谢!

【问题讨论】:

    标签: c# asp.net entity


    【解决方案1】:

    您可以使用IQuerable&lt;Request&gt; 代替IEnumerable&lt;Request&gt;

    然而,为了维护IQuerable&lt;Request&gt; 而拥有一个单独的BusinessLogic 类并不常见。

    需要数据的人可以直接致电_db.Requests

    var result = _db.Requests
       .Where(r => r.StatusId == Constants.STATUS_NOT_PROCESSED_ID)
       .ToList()
    

    或者,您可以创建一个像 this 这样的存储库层来保留所有逻辑。

    如果您不喜欢以上两种方法,可以使用Specification pattern

    【讨论】:

    • 编辑了主帖,因为您是第二个提到 IQueryable 的人。 IQueryable 不是一个选项,因为 List 不会从它继承,这是 api 处理器使用的。但是,在 api 处理器中使用 List 不是强制性的
    • DbSet 具有 AsQueryable 扩展方法。您可以使用_db.Requests.AsQueryable()。顺便问一下,您是否尝试实现 Repository Pattern
    【解决方案2】:

    尝试使用

    IQuerable<Request> Requests
    

    而不是

    IEnumerable<Request> Requests
    

    更新: 您可以使用存储库模式。我使用this 模式,它非常轻巧且可扩展。

    【讨论】:

    • 已经尝试过了,List 不继承自 IQueryable。除非你能推荐一些除了 List 之外的东西
    • 你可以使用 IQueryable i = _db.Request.AsQueryable();获取可查询对象。
    • DbContext 实现了两个接口,但显然两个 Where 实现(每个接口的)没有调用相同的代码。我建议不要将 List 换成更复杂的东西,以便匹配 IQueryable Linq 行为,而是将数据的加载方式与过滤方式分开。为什么不直接打电话给BusinessLogic.Requests = _db.Requests.Where(r =&gt; r.StatusId == Constants.STATUS_NOT_PROCESSED_ID).ToList()?似乎 apiprocessor 有获取实体列表的替代方法,所以您仍然想在该列表上进行过滤?为什么不单独对其进行预过滤?
    • @CPerkins 嗯,预过滤听起来是个有趣的想法。我会在等待更多答案时尝试一下
    猜你喜欢
    • 2015-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-12
    • 1970-01-01
    • 1970-01-01
    • 2021-03-19
    相关资源
    最近更新 更多