how to use linq "Take()" statement

Feb 14, 2012 at 12:20 PM

Hello

linq take statement is not supported in this project

any one have idea how to query first 20 (grid pagesize) from linq to ad queury?

and when page index change load next 20 results?

 

other limitation i cant filter by group (memberOf)

Any one has an idea how to filter by group?

tahnk you very much for your help

Feb 25, 2012 at 1:21 PM
Edited Mar 20, 2012 at 3:09 PM

1)

Take isn't supported, but it's pretty easy to add it yourself.  All of these changes are made to the DirectorySource class.  Just create a nullable class variable that gets set in the Parse method for Take.  I've highlighted the changes below:

public void Parse(Expression ex)
{
	var ce = ex as ConstantExpression;
	var mce = ex as MethodCallExpression;

	if (ce != null)
	{
		_source = ce.Value as IDirectorySource;
                originalType = _source.OriginalType;
        }
        else if (mce != null)
        {
                //
                // Should be extension methods on Queryable.
                //
                if (mce.Method.DeclaringType != typeof(Queryable))
                    throw new NotSupportedException("Detected invalid top-level method-call.");

                Parse(mce.Arguments[0]);

                //
                // First parameter to the method call represents the (unary) lambda in LINQ style.
                // E.g. (user => user.Name == "Bart") for a Where  clause
                //      (user => new { user.Name })   for a Select clause
                //
                switch (mce.Method.Name)
                {
                    //
                    // Builds the query LDAP expression.
                    //
                    case "Where":
                        BuildPredicate(((UnaryExpression)mce.Arguments[1]).Operand as LambdaExpression);
                        break;
                    //
                    // Builds the projection and filters the required properties.
                    //
                    case "Select":
                        BuildProjection(((UnaryExpression)mce.Arguments[1]).Operand as LambdaExpression);
                        break;
	            case "Take":
			_takeValue = (int)((ConstantantExpression)mce.Arguments[0]).Value;
		        break;
                    default:
                        throw new NotSupportedException("Unsupported query operator: " + mce.Method.Name);
                }
        }
	else
                throw new NotSupportedException("Invalid expression node detected.");
}

Once that's done you just need to check it and set it when you perform a search:

private IEnumerator<T> GetResults()
{
    DirectorySchemaAttribute[] attr = (DirectorySchemaAttribute[])originalType.GetCustomAttributes(typeof(DirectorySchemaAttribute), false);
    if (attr == null || attr.Length == 0)
        throw new InvalidOperationException("Missing schema mapping attribute.");

    string classQuery = String.Format("(objectClass={0})", attr[0].Schema);

    DirectorySearcher s = Helpers.CloneSearcher(
        _source.Searcher,
        !string.IsNullOrEmpty(query) ? String.Format("(&{0}{1})", classQuery, query) : classQuery,
        properties.ToArray()
    );
    if (_takeValue.HasValue) s.SizeLimit = _takeValue.Value;

    //rest of method to perform search...
}

 

As for paging the results, LDAP doesn't really support paging the way LINQ expects it to work.  Paging is kind of abstracted away and only exposed through a cookie returned from the server.  You can read more about it here: http://tools.ietf.org/html/rfc2696.  

You can tell the DirectorySearcher to get everything by setting a sufficiently large PageSize, but getting a subset and then going to get more is not possible from what I can tell.

2)

You can filter by group.  Just map the memberOf property as a string[] and do something like this:

context.Where(u => u.memberOf.Contains("[distinguished name of group]"))

This will find all users that are a member of that group.