This project is read-only.

System.NotImplementedException at LinqToLdap.QueryProvider.CreateQuery(Expression expression) - Closed

Dec 21, 2011 at 1:14 PM
Edited Dec 21, 2011 at 1:49 PM

I have a problem in a LightSwitch (also here and here) app I'm writing that uses your provider.  I'm getting a System.NotImplementedException: "The method or operation is not implemented." in LinqToLdap at LinqToLdap.QueryProvider.CreateQuery(Expression expression).

In fact, the stack trace goes on:

   at System.ServiceModel.DomainServices.Server.QueryComposer.QueryRebaser.Rebase(IQueryable source, IQueryable query)
   at System.ServiceModel.DomainServices.Server.QueryComposer.Compose(IQueryable source, IQueryable query)
   at System.ServiceModel.DomainServices.Server.DomainService.Query(QueryDescription queryDescription, IEnumerable`1& validationErrors, Int32& totalCount)
   ... and so on for quite a long way. :-)

The Target site is "System.Linq.IQueryable CreateQuery(System.Linq.Expressions.Expression)".

I've looked at the source and I can see that you've implemented the generic form of CreateQuery:

    public IQueryable<TElement> CreateQuery<TElement>(Expression expression)

but not the non-generic form:

    public IQueryable CreateQuery(Expression expression)

Is there a reason why you didn't implement this version?

My LightSwitch app uses a WCF RIA Service to call LinqToLdap.  In the course of my investigations, I created a native Silverlight app that also uses a WCF RIA Service.  I used exactly the same code for the WCF RIA Service the native Silverlight app as the LightSwitch app.  The Silverlight app receives the requested UserObjects from the service as expected.  I added code to the LightSwitch app and I can see the request going through and then the exception is generated.

Is there any chance you can implement it?  I found this which might help:

        public IQueryable CreateQuery(Expression expression)
        {
            Type elementType = TypeSystem.GetElementType(expression.Type);
            try
            {
                return (IQueryable)Activator.CreateInstance(typeof(DirectoryQuery<>).MakeGenericType(elementType), new object[] { this, expression });
            }
            catch (System.Reflection.TargetInvocationException tie)
            {
                throw tie.InnerException;
            }
        }
from here: http://msdn.microsoft.com/en-us/library/bb546158.aspx (in the second code block on the page) which it explains thus:

"The non-generic CreateQuery method uses reflection to obtain the element type of the sequence that the query it creates would return if it was executed. It then uses the Activator class to construct a new QueryableTerraServerData instance that is constructed with the element type as its generic type argument. The result of calling the non-generic CreateQuery method is the same as if the generic CreateQuery method had been called with the correct type argument."

There's a helper class called TypeSystem, at the bottom of the page, that you need as well.

Dec 22, 2011 at 2:04 AM
Edited Dec 22, 2011 at 2:08 AM

I've implemented the non-generic CreateQuery and checked it in.  I completely forgot I never implemented it.  I haven't touched the QueryProvider class in quite a while.  As for your timeout problems, I checked in a change that allows you to set it in seconds when configuring the connection factory.

var config = new LdapConfiguration();

config.ConfigureFactory("localhost")
     .ConnectionTimeoutIn(60);
Dec 22, 2011 at 11:28 AM

Superb support!  I've downloaded the latest code - since adding the connection timeout option I haven't seen one.  Thank you.

And my queries are running now, thanks to the non-generic implementation, though not without their own problems but I've posted a new thread about that as it's way over my head!