提供的解决方案不适用于 Chielus 提到的 CRM2013 SDK 程序集。
对于 CRM2013,您可以使用此扩展方法:
public static class QueryProviderExtensions
{
public static QueryExpression ToQueryExpression<T>(this IQueryable<T> items)
{
var queryProvider = items.Provider;
var queryProviderType = queryProvider.GetType();
var listType = typeof(List<>);
var projectionType = queryProviderType.Assembly.GetType("Microsoft.Xrm.Sdk.Linq.QueryProvider+Projection");
var navigationSourceType = queryProviderType.Assembly.GetType("Microsoft.Xrm.Sdk.Linq.QueryProvider+NavigationSource");
var linkLookupType = queryProviderType.Assembly.GetType("Microsoft.Xrm.Sdk.Linq.QueryProvider+LinkLookup");
var linkLookupListType = listType.MakeGenericType(linkLookupType);
object projection = null;
object source = Activator.CreateInstance(navigationSourceType, new object[] { null, null });
object linkLookups = Activator.CreateInstance(linkLookupListType);
bool throwIfSequenceIsEmpty = false;
bool throwIfSequenceNotSingle = false;
object[] arguments = new object[6];
arguments[0] = items.Expression;
arguments[1] = throwIfSequenceIsEmpty;
arguments[2] = throwIfSequenceNotSingle;
arguments[3] = projection;
arguments[4] = source;
arguments[5] = linkLookups;
var getQueryExpressionMethod = queryProviderType.GetMethod("GetQueryExpression", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, new[] {
typeof(Expression),
typeof(bool).MakeByRefType(),
typeof(bool).MakeByRefType(),
projectionType.MakeByRefType(),
navigationSourceType.MakeByRefType(),
linkLookupListType.MakeByRefType(),
}, null);
var queryExpression = (QueryExpression)getQueryExpressionMethod.Invoke(queryProvider, arguments);
return queryExpression;
}
public static string ToXml(this QueryExpression queryExpression, IOrganizationService service)
{
var request = new QueryExpressionToFetchXmlRequest { Query = queryExpression };
var response = (QueryExpressionToFetchXmlResponse)service.Execute(request);
return response.FetchXml;
}
}
像这样使用它:
// This can be any query
var query = (from e in contactSet.Query()
where e.LastName.Contains("e")
select e);
// This is where the magic happens
var queryExpression = query.ToQueryExpression();
// We can now add paging info
queryExpression.PageInfo = new PagingInfo()
{
PageNumber = 1,
Count = 50,
ReturnTotalRecordCount = true
};
// This will create a QueryExpressionToFetchXmlRequest, not needed for paging.
var xml = queryExpression.ToXml(service);
// Perform the actual request
var collection = service.RetrieveMultiple(queryExpression);
更多细节在这里:
https://social.msdn.microsoft.com/Forums/en-US/0026f1de-bc10-428d-ad15-18d34315c814/convert-linq-query-to-fetchxml-sdk-2013?forum=crm