我使用CRM 2011 RC(v5)LINQ-to-CRM提供程序编写了一个Linq to CRM查询。我有一个本地声明的List< T>我想加入CRM实体,我希望查询在CRM服务器上执行。一个例子可能会有所帮助:
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());
}
上面的代码编译并执行,但是,在检索整个CRM实体记录集之后,本地执行记录的过滤。显然,当CRM实体包含数千行时,查询将表现不佳甚至超时。
我已阅读有关IQueryable和IEnumerable的内容,并尝试使用AsQueryable()扩展方法转换List,该方法无效。我需要上面的Linq查询来运行这样的SQL:
SELECT a.*
FROM customAccountEntity AS a
WHERE a.account_number IN ('123', '456');
如果想加入多个字段,请使用临时表。我怎么能做到这一点?
答案 0 :(得分:13)
经过大量的敲击和研究后,我使用Predicate Builder和LINQKit解决了这个问题。我需要使用本地List&lt; T&gt;中的键创建一个基于Or的谓词。然后将谓词传递给Where LINQ扩展方法。重要的是,我需要调用LINQKit公开的 AsExpandable 扩展方法。所以我的代码看起来像这样:
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);
}
以上代码将在CRM服务器上运行SQL语句,如下所示:
SELECT a.*
FROM customAccountEntity AS a
WHERE a.account_number = '123' OR a.account_number = '456'
这意味着我可以在运行时创建一个动态where子句,并知道我的查询将在CRM SQL Server上运行过滤逻辑。希望这有助于其他人。
答案 1 :(得分:1)
您可以简单地使用连接表达式进行过滤,而不是使用谓词。
var myLinqToCrmQuery = from ax in myObject.ListOfAccounts
join cx in orgContext.CreateQuery<customAccountEntity> on ax.AccountNumber equals cx.account_number
select cx;
干杯, 卢卡斯
答案 2 :(得分:0)
编辑:尝试一下:
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());
}
编辑:如果您查询提供程序不支持包含,使用多个OR构建Where条件,您可以使用predicate builder来轻松实现