【问题标题】:Convert Linq expression to QueryExpression or FetchXML将 Linq 表达式转换为 QueryExpression 或 FetchXML
【发布时间】:2011-07-18 22:27:07
【问题描述】:

我的最终目标是将 linq 表达式转换为获取 xml。我打算在 MS CRM 2011 中将 fetch XML 用于自定义网格。

通过这篇文章,我可以将 QueryExpression 转换为 FetchXML http://mileyja.blogspot.com/2011/07/convert-queryexpression-to-fetchxml.html

但我不知道如何将 Linq 表达式转换为 QueryExpression。当我说 linq 表达式时,我指的是 IQueryable.

类型的对象

有人有这方面的经验或知道如何做吗?

干杯

【问题讨论】:

    标签: linq dynamics-crm fetchxml


    【解决方案1】:

    提供的解决方案不适用于 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

    【讨论】:

      【解决方案2】:

      您可以使用反射获取QueryExpression,从IQuerable&lt;T&gt;获取提供者并对其调用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 属性。

      【讨论】:

      • 这在 Dynamics CRM 2013 中被破坏了。有关支持的替代方案,请参阅此博文:hashtagcrm.com/?p=157
      【解决方案3】:

      在 LINQ 表达式上调用 ToString() 应该返回 FetchXML

      【讨论】:

      • 我试过了,但它只返回对象类型名称。我找到了对此的引用,但仅适用于 CRM 4.0。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-29
      • 2022-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多