2011-02-09 13 views
12

Napisałem zapytanie Linq do CRM za pomocą dostawcy CRM 2011 RC (v5) LINQ-to-CRM. Mam lokalnie zadeklarowaną Listę <T>, którą chcę dołączyć do jednostki CRM i chcę, aby zapytanie zostało wykonane na serwerze CRM. Przykładem może pomóc:LINQ to Dynamics CRM Zapytanie o filtrowanie rekordów lokalnie

MyObject myObject = new MyObject(); 
List<myAccount> myAccountsList = new List<myAccount>(); 

myAccountsList.Add(new myAccount() {AccountNumber = "123"}; 
myAccountsList.Add(new myAccount() {AccountNumber = "456"}; 

myObject.ListOfAccounts = myAccountsList; 

var accountsQuery = from ax in myObject.ListOfAccounts 
        join a in orgContext.CreateQuery<customAccountEntity>() on ax.AccountNumber equals a.account_number 
        select a; 

foreach(var item in accountsQuery) 
{ 
    Console.WriteLine("Id of record retrieved: " + a.Id.ToString()); 
} 

Powyższy kod kompiluje i wykonuje jednak filtrowanie rekordów odbywa się lokalnie po pobraniu całego podmiotu CRM rekordów. Oczywiście, gdy jednostka CRM zawiera tysiące wierszy, zapytanie będzie działało słabo, a nawet limit czasu.

Przeczytałem o IQueryable i IEnumerable i próbowałem konwertować listę przy użyciu metody rozszerzenia AsQueryable(), która nie przyniosła skutku. Potrzebuję mojego powyższego zapytania Linq do uruchomienia SQL w następujący sposób:

SELECT a.* 
FROM customAccountEntity AS a 
WHERE a.account_number IN ('123', '456'); 

Lub użycie tabeli tymczasowej, jeśli chcesz dołączyć do wielu pól. Jak mogę to zrobić?

Odpowiedz

12

Po dużo headbangingu i badań Rozwiązałem problem, używając Predicate Builder i LINQKit. Potrzebuję stworzyć predykat oparty na Or lub używając kluczy w mojej lokalnej liście < T> następnie przekazać predykat do metody rozszerzenia Where LINQ. Co ważne, muszę zadzwonić do metody rozszerzania AsExpandable wyeksponowanej przez LINQKit. Więc mój kod będzie wyglądać następująco:

var predicate = PredicateBuilder.False<customAccountEntity>(); 
// Loop through the local List creating an Or based predicate 
foreach (var item in myAccountsList) 
{ 
    string temp = item.AccountNumber; 
    predicate = predicate.Or (x => x.customCrmEntityAttribute == temp); 
} 
// The variable predicate is of type Expression<Func<customAccountEntity, bool>> 
var myLinqToCrmQuery = from ax in myObject.ListOfAccounts 
         from cx in orgContext.CreateQuery<customAccountEntity>().AsExpandable().Where(predicate) 
         where ax.AccountNumber == cx.account_number 
         select cx; 

foreach (resultItem in myLinqToCrmQuery) 
{ 
    Console.WriteLine("Account Id: " + resultItem.Id); 
} 

Powyższy kod będzie działał instrukcji SQL na serwerze CRM jak to:

SELECT a.* 
FROM customAccountEntity AS a 
WHERE a.account_number = '123' OR a.account_number = '456' 

W ten sposób można utworzyć dynamiczną gdzie klauzula przy starcie i wiedzieć że moje zapytanie uruchomi logikę filtrowania na serwerze SQL CRM. Mam nadzieję, że to pomoże komuś innemu.

0

Edit: Spróbuj, że jeden:

MyObject myObject = new MyObject(); 
List<myAccount> myAccountsList = new List<myAccount>(); 

myAccountsList.Add(new myAccount() {AccountNumber = "123"}; 
myAccountsList.Add(new myAccount() {AccountNumber = "456"}; 

myObject.ListOfAccounts = myAccountsList; 

var accountNumbers = myObject.ListOfAccounts.Select(a => a.AccountNumber); 

var accountsQuery = orgContext.CreateQuery<customAccountEntity>() 
           .Where(a => accountNumbers.Contains(a.account_number)); 

foreach(var item in accountsQuery) 
{ 
    Console.WriteLine("Id of record retrieved: " + a.Id.ToString()); 
} 

Edit: jeśli zapytanie dostawcy nie obsługują Zawiera, zbudować WHERE warunek wieloosobowych lub można użyć predicate builder aby takie łatwe

+0

jestem już przy użyciu dostawcy zapytań LINQ-CRM - Czy mogę używać więcej niż jednego dostawcy w tej samej kwerendy? – Iftekhar

+0

Ok po przyjrzeniu się kwerendy, myślę, że powinieneś zrobić to na odwrót (bez łączenia, ale zawiera) – Guillaume86

+0

Chcę, aby moje zapytanie zostało przetłumaczone na SQL i filtrowanie do uruchomienia na serwerze SQL. Metoda rozszerzenia Contains po prostu filtruje lokalnie. – Iftekhar

1

Zamiast grać z predykatami można również po prostu użyć wyrażenia sprzężenia do filtrowania.

var myLinqToCrmQuery = from ax in myObject.ListOfAccounts 
          join cx in orgContext.CreateQuery<customAccountEntity> on ax.AccountNumber equals cx.account_number      
          select cx; 

Cheers, Łukasz

+1

Chciałem uruchomić kwerendę na serwerze. W wyrażeniu sprzężenia filtrowanie odbywa się lokalnie na kliencie. – Iftekhar

Powiązane problemy