2011-03-01 3 views
0

У меня есть EDMX с агентом, клиентом, транзакцией и формой. У агента есть Клиенты, у которых есть транзакции и транзакции.Запрос Linq-to-Entities от SQL

Я хочу использовать проекцию, чтобы получить все сущности для агента сразу, чтобы добавить иерархическое древовидное представление. Древовидный вид должен показывать только транзакции и формы по выбранному году.

Мой запрос в 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 контекст , ObjectParameterCollection parameterValues) при System.Data.Objects.ObjectQuery 1.GetResults(Nullable 1 forMergeOption) при System.Data.Objects.ObjectQuery validationErrors, Int32 & TOTALCOUNT) при System.ServiceModel.DomainServices.Hosting.QueryProcessor.Process [TEntity] (DomainService domainService, DomainOperationEntry queryOperation, Object [] параметры, ServiceQuery servic eQuery, IEnumerable 1& validationErrors, Int32& totalCount) at System.ServiceModel.DomainServices.Hosting.QueryOperationBehavior 1.QueryOperationInvoker.InvokeCore (экземпляра объекта, Object [] входы, Object [] & выходов)

Я в поиске, что эта ошибка возникает только на определенных данных. Кажется, что-то не так?

ответ

0

Если вы хотите достичь JOIN в SQL, почему вы не используете JOIN в LINQ?

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-сервер.

+0

Спасибо за ответ, ваше предложение помогло мне понять LINQ немного лучше, однако, если вы посмотрите на SQL-запрос, который я опубликовал, мне нужно вернуть Клиентов, все транзакции для клиента и все формы для каждого сделка. У меня возникли проблемы с объединением двух соединений. Любая дополнительная помощь будет принята с благодарностью. – Ruggeri

0

Я решил проблему со следующим кодом. Я так новичок в 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).

Спасибо всем за вашу помощь!

Смежные вопросы