代码之家  ›  专栏  ›  技术社区  ›  SamiHuutoniemi

实体框架、存储库模式和let语句

  •  3
  • SamiHuutoniemi  · 技术社区  · 7 年前

    试图用实体框架实现正确的存储库模式,我遇到了let语句的一些问题。我想做的是:

    var customer = (from cus in Customers.GetAll()
                    let brokerExists = InsuredBrokers.GetAll().Any(ib => ib.INS_Id == cus.INS_Id)
                // ... more stuff
    

    但这会给我一个错误

    系统不支持例外: 'LINQ to Entities不识别 方法 '系统。林克。IQueryable'1[ 剪断 .数据模型。EA\U INB\U InsuredBrokers\U TB] GetAll()'方法,而此方法无法转换为存储 表达式。”

    相反,我能做的是:

    var customer = (from cus in Customers.GetAll()
                let brokerExists = _context.Set<EA_INB_InsuredBrokers_TB>().Any(ib => ib.INS_Id == cus.INS_Id)
                // ... more stuff
    

    然而,这打破了使用存储库模式的任何一点。当我搜索答案时,人们会说自己把它放在一个查询中,并从内存中引用它,但因为我实际上有客户的Id( INS_Id )在let声明中,我不能这样做。

    GetAll() 类似于:

    public IQueryable<T> GetAll()
    {
        return _context.Set<T>().AsQueryable();
    }
    

    有什么聪明的方法可以绕过这个问题吗?

    2 回复  |  直到 7 年前
        1
  •  2
  •   Evk    7 年前

    你得走了 InsuredBrokers.GetAll() 查询之外:

    var allBrokers = InsuredBrokers.GetAll();
    var customer = (from cus in Customers.GetAll()
                let brokerExists = allBrokers.Any(ib => ib.INS_Id == cus.INS_Id)
            // ... more stuff
    

    那它就可以正常工作了。自从 GetAll 退货 IQueryable 并且您不需要枚举它,这并没有负面影响,仍然会有一个对数据库的查询,就像您的示例中的 _context .

    原因是 let 语句的编译方式如下:

    Customers.GetAll().Select(cus => new {cus, brokerExists = InsuredBrokers.GetAll().Any(ib => ib.INS_Id == cus.INS_Id)}
    

    也就是说你的电话 被保险经纪人。GetAll() 是表达式树的一部分(位于 Select 表达式),实体框架不能(不会)调用它来获取值。它将尝试将其转换为SQL查询,但不知道如何处理 GetAll公司 方法

        2
  •  -1
  •   Shyam Poovaiah    7 年前

    我想你是想做一个左连接。

    您的查询:

    var query = from customer in Customers
                 join broker in InsuredBrokers
                 on customer.InsertId equals broker.InsertId
                 into resutGroups
                select new { Name = broker.Name, InsertId= broker.InsertId};
    

    如果您需要无马赫数的条目,请使用 DefaultIfEmpty .

    您可以参考 this 更多相同的信息。