我的最终目标是将linq表达式转换为fetch xml。我打算在MS CRM 2011中使用fetch XML进行自定义网格。
在本文中,我可以将QueryExpression转换为FetchXML http://mileyja.blogspot.com/2011/07/convert-queryexpression-to-fetchxml.html
但我不知道如何将Linq表达式提供给QueryExpression。当我说linq表达式时,我指的是IQueryable<>类型的对象。
任何人对此有任何经验或知道如何?
干杯
答案 0 :(得分:4)
所提供的解决方案不适用于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);
此处有更多详情:
答案 1 :(得分:2)
您可以使用反射获取QueryExpression
,从IQuerable<T>
获取提供程序并在其上调用Translate方法。
这是我正在使用的扩展方法:
public static QueryExpression ToQueryExpression(this IQueryable @this)
{
var provider = @this.Provider;
var translateMethod = provider.GetType().GetMethod("Translate");
var query = (QueryExpression)translateMethod.Invoke(provider, new object[] { @this.Expression });
return query;
}
如果您在C#中使用某种动态包装器进行反射,例如ExposedObject,您可以像这样做:
public static QueryExpression ToQueryExpression(this IQueryable @this)
{
dynamic provider = ExposedObject.From(@this.Provider);
return provider.Translate(@this.Expression);
}
至于抓取,您需要QueryExpression
,然后发出请求QueryExpressionToFetchXmlRequest
,该请求返回QueryExpressionToFetchXmlResponse
响应,其中包含属性FetchXml
。
答案 2 :(得分:0)
在LINQ表达式上调用ToString()应该返回FetchXML