Преобразование выражения Linq в QueryExpression или FetchXML

Моя конечная цель - преобразовать выражение linq для извлечения xml. Я намерен использовать выборку XML для пользовательских сеток в MS CRM 2011.

Из этой статьи я могу преобразовать QueryExpression в FetchXML http://mileyja.blogspot.com/2011/07/convert-queryexpression-to-fetchxml.html

Но я не знаю, как преобразовать выражение Linq в QueryExpression. Когда я говорю выражение linq, я имею в виду объект типа IQueryable‹>.

Кто-нибудь имел опыт в этом или знает как?

Ваше здоровье


person Chaos    schedule 18.07.2011    source источник


Ответы (3)


Предоставленное решение не работает для сборок CRM2013 SDK, как упоминалось Chielus.

Для 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

person Ericvf    schedule 25.10.2014

вы можете использовать отражение, чтобы получить 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.

person Gutek    schedule 26.06.2012
comment
Это не работает в Dynamics CRM 2013. См. этот блог, чтобы узнать о поддерживаемой альтернативе: hashtagcrm.com/?p= 157 - person Chielus; 02.06.2014

вызов ToString() в выражении LINQ должен возвращать FetchXML

person Tyler Smith    schedule 05.08.2011
comment
Я пробовал это, но он просто возвращает имя типа объекта. Я нашел ссылки на это, но только для CRM 4.0. - person Chaos; 30.08.2011