【问题标题】:LINQ to SQL throws SQL Exception using local collectionLINQ to SQL 使用本地集合引发 SQL 异常
【发布时间】:2012-10-29 20:26:13
【问题描述】:
Amounts = 
    Context.Ppm_TblCodeType
    .Where(bc => bc.OrganisationId == Contract.OrganisationId)
    .Select(bc => new MacroPaymentValue
    {
        Code = bc.CodeTypeCode,
        ShortName = bc.ShortDescription,
        ValueForPayment = visits
            .Where(v => v.Detail.CodeTypeCode == bc.CodeTypeCode)
            .Sum(v => v.Detail.Charge != null ? v.Detail.Charge.Value : 0)
     }).ToArray();

我遇到了异常:本地序列不能在查询运算符的 LINQ to SQL 实现中使用,但 Contains 运算符除外。

我猜这与 .Sum() 调用有关...如何修改它以避免异常?

【问题讨论】:

    标签: c# .net linq linq-to-sql sqlexception


    【解决方案1】:

    发生这种情况是因为您尝试在代码中使用 visits 作为查询的一部分,这是一个本地序列,而 LINQ to SQL 无法将其转换为 SQL。

    查看您的代码,我认为您最好在内存中有查询结果后填充 ValueForPayment。比如:

    Amounts = 
        Context.Ppm_TblCodeType
        .Where(bc => bc.OrganisationId == Contract.OrganisationId)
        .Select(bc => new MacroPaymentValue
        {
            Code = bc.CodeTypeCode,
            ShortName = bc.ShortDescription,
            CodeTypeCode = bc.CodeTypeCode,
            ValueForPayment = 0
         }).ToArray();
    
    foreach(var bc in Amounts) 
    {
        bc.ValueForPayment = visits
                .Where(v => v.Detail.CodeTypeCode == bc.CodeTypeCode)
                .Sum(v => v.Detail.Charge != null ? v.Detail.Charge.Value : 0)
    }
    

    【讨论】:

    • 这正是我为解决问题所做的。看起来更经典,而不是 LINQy……但这对于工作和可读代码来说是一个小小的牺牲。
    【解决方案2】:

    它抛出异常是因为您尝试使用visits,而不是因为您正在调用 sum()。如果您包含创建访问列表的代码部分可能会有所帮助...

    这是从哪里来的,是否可以在同一语句中查询?

    所以这样的事情会起作用:

    Context...Select(bc => new MacroPaymentValue() 
    {
        //stuff
        ValueForPayment =     bc.visits.sum(...)
    });
    

    事实上,我注意到在这个查询的末尾你强制它使用 ToArray()。如果您对访问查询执行相同的操作,它将查询转换为本地序列。只需去掉访问查询中的 ToArray() 部分,就可以得到一个可用于其他 linq 查询的 IQueryable。

    因此,如果确实需要来自 TblCodeType 之外的访问,您可以确保不使用 ToArray()。

    基本上,您不能在 linq to sql 查询中使用本地数组(大部分情况下)。不过,您可以在 linq to sql 查询中使用另一个查询。如果您调用 ToArray() 或 ToList(),它将实际运行查询,获取结果并将其存储在本地序列中(数组或列表取决于您调用的内容。)但是,如果您不这样做,则在您实际开始使用值之前,不会运行查询。这样,查询就一直是一个查询,并且可以安全地用于其他查询。

    【讨论】:

    • 好点...我模拟了一个测试应用程序并将访问保留为 IQueryable,一旦我执行了 .ToArray(),它就是一个查询的怪物,但很有魅力。不幸的是,我无法在我的真实应用程序中执行此操作,因此已将其他答案标记为已接受。要学习的 LINQ 太多了……没有双关语。
    • 可能想与负责访问查询的人一起工作......还有效率要担心。一个怪物查询优于两个单独的查询。另外我要答案点! ;)
    • 哈!我可以引用你吗?我猜想,这是我与那个开发团队聊天的一个很好的理由。这是我开始在这里发布问题的唯一原因,我是一个有竞争力的小伙子。
    • 很高兴有积分!只是想插话说,使用 LINQ 很可能生成查询,这些查询确实不值得减少对数据库的调用。我经常看到长达数百行的 LINQ 查询——主要使用 EF 继承模型——并且只需将其拆分为多个调用就可以节省大量时间。您仍然必须测试所有这些东西才能知道如何最好地实施特定操作。在这种情况下,尽管我怀疑 @Telos 的建议仅基于表达式的结构会更快。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-03
    • 1970-01-01
    • 2010-12-03
    相关资源
    最近更新 更多