【问题标题】:Linq-to-Entities Query from SQL来自 SQL 的 Linq-to-Entities 查询
【发布时间】:2011-03-01 22:19:19
【问题描述】:

我有一个带有代理、客户、交易和表单的 EDMX。代理有客户,客户有交易,交易有表格。

我想使用投影来一次获取代理的所有实体以放入分层树视图中。树视图只需要按所选年份显示交易和表格。

我在 SQL 中的查询看起来像这样:

SELECT c.*, t.*, f.* FROM Client c
INNER JOIN Client_Bucket_Client cbc on cbc.Client_GUID = c.Client_GUID
INNER JOIN Agent_Client_Bucket acb on acb.Client_Bucket_GUID = cbc.Client_Bucket_GUID
LEFT OUTER JOIN [Transaction] t on t.Client_GUID = c.Client_GUID
LEFT OUTER JOIN [Form] f on f.Transaction_GUID = t.Transaction_GUID
WHERE f.Year = 2011 AND t.Year = 2011 AND acb.Agent_GUID = 'A29B6E94-3F1B-E011-B68A-001F290A2D4A'
ORDER BY c.Last_Change_Date desc, c.File_Under

现在我的 linq 看起来像这样:

var clients = from client in ObjectContext.Clients
                  join cbc in ObjectContext.Client_Bucket_Client on client.Client_GUID equals cbc.Client_GUID
                  join acb in ObjectContext.Agent_Client_Bucket on cbc.Client_Bucket_GUID equals acb.Client_Bucket_GUID
                  where acb.Agent_GUID == agentGuid
                  orderby client.Last_Change_Date descending, client.File_Under
                  select client;

    var clientInfos =
        from c in clients
        select new
        {
            Client = c,
            TransactionInfos = ObjectContext.Transactions
                .Where(t => t.Client_GUID == c.Client_GUID && t.Year == year)
                .Select(t => new
                {
                    Transaction = t,
                    ToAttach = ObjectContext.Forms.Where(f => f.Transaction_GUID == t.Transaction_GUID && f.Year == year)
                })
        };

    // Looping over this query will hit the database *once*
    foreach (var info in clientInfos)
    {
        foreach (var transactionInfo in info.TransactionInfos)
        {
            transactionInfo.Transaction.Forms.Attach(transactionInfo.ToAttach);
        }

        var tt = info.TransactionInfos.ToList(); //.Select(t => t.Transaction);

        var trans = tt.Select(t => t.Transaction);

        info.Client.Transactions.Attach(trans);
    }

    // Return a queryable object; constructing a new query from this will hit the database one more time
    return clients;

但我得到一个错误:

查询“GetTopLevelData”的加载操作失败。执行命令定义时发生错误。有关详细信息,请参阅内部异常。内部异常消息:超时已过期。在操作完成之前超时时间已过或服务器没有响应。

这是堆栈跟踪:

在 System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior 行为) 在 System.Data.Objects.Internal.ObjectQueryExecutionPlan.Execute[TResultType](ObjectContext context, ObjectParameterCollection parameterValues) 在 System.Data.Objects.ObjectQuery 1.GetResults(Nullable1 forMergeOption) 在 System.Data.Objects.ObjectQuery1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() at RealForms.Web.Data.RealFormsService.GetTopLevelData(Guid agentGuid, Int32 year) in C:\Users\Bryan\Documents\Visual Studio 2010\Projects\RealForms\RealForms.Web.Data\RealFormsService.cs:line 590 at GetTopLevelData(DomainService , Object[] ) at System.ServiceModel.DomainServices.Server.ReflectionDomainServiceDescriptionProvider.ReflectionDomainOperationEntry.Invoke(DomainService domainService, Object[] parameters) at System.ServiceModel.DomainServices.Server.DomainOperationEntry.Invoke(DomainService domainService, Object[] parameters, Int32& totalCount) at System.ServiceModel.DomainServices.Server.DomainService.Query(QueryDescription queryDescription, IEnumerable1& validationErrors, Int32& totalCount) 在 System.ServiceModel.DomainServices.Hosting.QueryProcessor.Process[TEntity](DomainService domainService, DomainOperationEntry queryOperation, Object[] 参数, ServiceQuery serviceQuery, IEnumerable1& validationErrors, Int32& totalCount) at System.ServiceModel.DomainServices.Hosting.QueryOperationBehavior1.QueryOperationInvoker.InvokeCore(Object instance, Object[] inputs, Object[]& outputs)

我发现这个错误只发生在某些数据上。好像有些东西是空的??

【问题讨论】:

    标签: c# linq-to-entities


    【解决方案1】:

    如果你想在 SQL 中实现JOIN 为什么不在 LINQ 中使用JOIN

    http://msdn.microsoft.com/en-us/library/bb534675.aspx

    这就是您可以将客户加入交易的方式:

    var clientTransactions = clients
           .Join(ObjectContext.Transactions, c => c.Client_GUID, t => t.Client_GUID, 
                        (c,t) => new {Client = c, Transaction = t});
    

    很难预测哪个 SQL 查询会生成您的 linq,所以我更喜欢使用这种语法进行 JOIN。

    P.S.:您遇到了超时 - 这绝对取决于数据,尤其是数据量。尝试分析您的 LINQ 发送到 SQL 服务器的查询。

    【讨论】:

    • 感谢您的回复,您的建议帮助我更好地理解了 LINQ,但是如果您查看我发布的 SQL 查询,我需要返回客户端、客户端的所有事务以及所有每笔交易的表格。我无法将两个连接嵌套在一起。任何额外的帮助将不胜感激。
    【解决方案2】:

    我已经用下面的代码解决了我的问题。我对 Linq-to-Entities 很陌生,我不确定这是否是最好的或首选的方法,但它对我有用。

    public IQueryable<Client> GetTopLevelData(Guid agentGuid, int year)
    {
        var clients = from client in ObjectContext.Clients
                      join cbc in ObjectContext.Client_Bucket_Client on client.Client_GUID equals cbc.Client_GUID
                      join acb in ObjectContext.Agent_Client_Bucket on cbc.Client_Bucket_GUID equals acb.Client_Bucket_GUID
                      where acb.Agent_GUID == agentGuid
                      orderby client.Last_Change_Date descending, client.File_Under
                      select client;
    
        var clientTransactions = clients
                    .Join(ObjectContext.Transactions, c => c.Client_GUID, t => t.Client_GUID,
                                (c, t) => new { Transaction = t });
    
        var clientForms = clientTransactions
                    .Join(ObjectContext.Forms, t => t.Transaction.Transaction_GUID, f => f.Transaction_GUID,
                                (t, f) => new { Form = f });
    
        foreach (var client in clients)
        {
            var clientTrans = from trans in clientTransactions where trans.Transaction.Client_GUID == client.Client_GUID && trans.Transaction.Year == year select trans;
            foreach (var trans in clientTrans)
            {
                client.Transactions.Attach(trans.Transaction);
    
                var transForms = from forms in clientForms where forms.Form.Transaction_GUID == trans.Transaction.Transaction_GUID && forms.Form.Year == year select forms;
                foreach (var form in transForms)
                {
                    trans.Transaction.Forms.Attach(form.Form);                                                             
                }
            }
        }
    
        return clients;
    }
    

    我研究了如何在 Linq 中嵌套连接,但无法使任何工作,所以在这里我拉出子事务并形成记录,然后加载带有结果的投影客户端对象。我不再收到超时或 (Nullable1 forMergeOption) 错误。

    感谢大家的帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多