none
IQueryable extend by method LastOrNull RRS feed

  • Question

  • Good day to ask for urgent assistance in writing a method with Expression
    need to get the last record of IQueryable
    manual option all works, in Expression  can `t finish the method.

    Please help and that does come to a standstill!

    public class User
    {
      public int Id {get;set;}
      public string Name {get;set;}
    }
    
    public List<User> GetDemoData()
    {
       return new List<User>
    	{
    		new User(){Id=1, Name="Alex"},
    		new User(){Id=2, Name="Betty"},
    		new User(){Id=3, Name="Gannet"}
    	};
    }
    
    public static class IQueryableEx
        {
            public static TSource LastOrNull<TSource>(
                this IQueryable<TSource> source,
                Expression<Func<TSource, object>> f)
                where TSource:class            
            {
                var max = source.Max(f);
                TSource lastItem=null;
    			
    			//can `t finish the 
    			//lastItem = source.Single(????????????);
    			
    	        return lastItem;
            }
    	}
    
    void Main()
    {
        var data = GetDemoData().AsQueryable();
    	
    	// Return last User Gannet
    	var max=data.Max(u=>u.Id);
    	var lastUser=data.Single(u=>u.Id==max); // WorkFine
    	//lastUser.Dump();	
    	
    	// Return last User Gannet by extension	
    	// not end coded
    	lastUser=data.LastOrNull(u=>u.Id); // can `t finish the method. 	
    	// lastUser.Dump();	
    }
    
    Please help!

    Monday, January 21, 2013 11:05 AM

All replies

  • Hi,

    http://msdn.microsoft.com/en-us/library/bb504095.aspx (LastOrDefault) doesn't fit your needs ?


    Please always mark whatever response solved your issue so that the thread is properly marked as "Answered".

    • Proposed as answer by Alexander Sun Tuesday, January 22, 2013 7:30 AM
    Monday, January 21, 2013 12:51 PM
  • IMNSHO, you should revert the order and use FirstOrDefault(). That way you do not force the database to produce all those rows you are gonna throw away anyway.

    You did specify the order, didn't you?!?


    ----------------------------------
    http://jendaperl.blogspot.com
    A Perl developer in the world of C#

    Monday, January 21, 2013 1:59 PM
  • Blame forgot mentioning that my LINQ to Entities that do not support many of the methods.

    Monday, January 21, 2013 2:16 PM
  • Yes of course the toilet, and it's a good idea to do a reverse sort request and take the first value!

    But only one problem in a real database query sorted and next sort by reverse order loong execute

    var users = ...GetQueryable<Users>().OrderBy(u => u.Id);
    
    1)var user = users.OrderByDescending(user => user.ID).FirstOrDefault(); // Execute over 9sec.
    
    2)var user = users.LastOrNull(u => u.id); // Execute 3.3sec
    
    

    I have yet found a solution:

    public static TEntity LastOrNull<TEntity, TValue>
                (this IQueryable<TEntity> query,
                 Expression<Func<TEntity, TValue>> keyFieldPredicate)
            {
                if (keyFieldPredicate == null) throw new ArgumentNullException("keyFieldPredicate");
    
                ParameterExpression p = keyFieldPredicate.Parameters.Single();
    
                if (query.LongCount() == 0) return default(TEntity);
    
                var max = query.Max(keyFieldPredicate);
    
                var equalsOne =
                    (Expression) Expression.Equal(keyFieldPredicate.Body, Expression.Constant(max, typeof (TValue)));
    
                return query.Single(Expression.Lambda<Func<TEntity, bool>>(equalsOne, p));
            }
    

    • Proposed as answer by Alexander Sun Tuesday, January 22, 2013 7:29 AM
    Monday, January 21, 2013 2:46 PM
  • Thank you responded to a call for help!

    You think you can improve the solution?
    • Marked as answer by Vicheslav Monday, January 21, 2013 9:21 PM
    • Unmarked as answer by Vicheslav Monday, January 21, 2013 9:22 PM
    Monday, January 21, 2013 2:51 PM