Top linq Questions

List of Tags
360
msony

I have two tables, movies and categories, and I get an ordered list by categoryID first and then by Name.

The movie table has three columns, ID, Name, and CategoryID. The category table two has columns, ID, and Name.

I tried something like the following, but it didn't work.

var movies = _db.Movies.OrderBy( m => { m.CategoryID, m.Name })
Answered By: Nathan W ( 832)

This should work for you:

Var movies = _db.Movies.Orderby(c => c.Category).ThenBy(n => n.Name)
283
Jon Skeet

Background: Over the next month, I'll be giving three talks about or at least including LINQ in the context of C#. I'd like to know which topics are worth giving a fair amount of attention to, based on what people may find hard to understand, or what they may have a mistaken impression of. I won't be specifically talking about LINQ to SQL or the Entity Framework except as examples of how queries can be executed remotely using expression trees (and usually IQueryable).

So, what have you found hard about LINQ? What have you seen in terms of misunderstandings? Examples might be any of the following, but please don't limit yourself!

  • How the C# compiler treats query expressions
  • Lambda expressions
  • Expression trees
  • Extension methods
  • Anonymous types
  • IQueryable
  • Deferred vs immediate execution
  • Streaming vs buffered execution (e.g. OrderBy is deferred but buffered)
  • Implicitly typed local variables
  • Reading complex generic signatures (e.g. Enumerable.Join)
Answered By: JaredPar ( 272)

Delayed execution

262
Calanus

I'm trying to perform a LINQ query on a DataTable object and bizarrely I am finding that performing such queries on DataTables is not straightforward. For example:

var results = from myRow in myDataTable
where results.Field("RowNo") == 1
select results;

This is not allowed. Any ideas how to get something like this working? I'm amazed that LINQ queries are not allowed on DataTables!

Answered By: Collin K ( 362)

You can't query against the DataTable's Rows collection, since DataRowCollection doesn't implement IEnumerable<T>. You need to use the AsEnumerable() extension for DataTable. Like so:

var results = from myRow in myDataTable.AsEnumerable()
where myRow.Field<int>("RowNo") == 1
select myRow;

And as Keith says, you'll need to add a reference to System.Data.DataSetExtensions

AsEnumerable() returns IEnumerable<DataRow>. If you need to convert IEnumerable<DataRow> to a DataTable, use the CopyToDataTable() extension.

226
tags2k

I'd like to do the equivalent of the following in LINQ, but I can't figure out how:

IEnumerable<Item> items = GetItems();
items.ForEach(i => i.DoStuff());

What is the real syntax?

Answered By: Fredrik Kalseth ( 277)

There is no ForEach extension for IEnumerable; only for List<T>. So you could do

items.ToList().ForEach(i => i.DoStuff());

Alternatively, write your own ForEach extension:

public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
    foreach(T item in enumeration)
    {
        action(item);
    }
}
221
John Sheehan

I found an example in the VS2008 Examples for Dynamic LINQ that allows you to use a sql-like string (e.g. OrderBy("Name, Age DESC")) for ordering. Unfortunately, the method included only works on IQueryable<T>. Is there any way to get this functionality on IEnumerable<T>?

Answered By: Marc Gravell ( 366)

Just stumbled into this oldie...

To do this without the dynamic LINQ library, you just need the code as below. This covers most common scenarios including nested properties.

To get it working with IEnumerable<T> you could add some wrapper methods that go via AsQueryable - but the code below is the core Expression logic needed.

    public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string property)
    {
        return ApplyOrder<T>(source, property, "OrderBy");
    }
    public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string property)
    {
        return ApplyOrder<T>(source, property, "OrderByDescending");
    }
    public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> source, string property)
    {
        return ApplyOrder<T>(source, property, "ThenBy");
    }
    public static IOrderedQueryable<T> ThenByDescending<T>(this IOrderedQueryable<T> source, string property)
    {
        return ApplyOrder<T>(source, property, "ThenByDescending");
    }
    static IOrderedQueryable<T> ApplyOrder<T>(IQueryable<T> source, string property, string methodName) {
        string[] props = property.Split('.');
        Type type = typeof(T);
        ParameterExpression arg = Expression.Parameter(type, "x");
        Expression expr = arg;
        foreach(string prop in props) {
            // use reflection (not ComponentModel) to mirror LINQ
            PropertyInfo pi = type.GetProperty(prop);
            expr = Expression.Property(expr, pi);
            type = pi.PropertyType;
        }
        Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);
        LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);

        object result = typeof(Queryable).GetMethods().Single(
                method => method.Name == methodName
                        && method.IsGenericMethodDefinition
                        && method.GetGenericArguments().Length == 2
                        && method.GetParameters().Length == 2)
                .MakeGenericMethod(typeof(T), type)
                .Invoke(null, new object[] {source, lambda});
        return (IOrderedQueryable<T>)result;
   } 

Edit: it gets more fun if you want to mix that with dynamic - although note that dynamic only applies to LINQ-to-Objects (expression-trees for ORMs etc can't really represent dynamic queries - MemberExpression doesn't support it). But here's a way to do it with LINQ-to-Objects. Note that the choice of Hashtable is due to favorable locking semantics:

using Microsoft.CSharp.RuntimeBinder;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Runtime.CompilerServices;
static class Program
{
    private static class AccessorCache
    {
        private static readonly Hashtable accessors = new Hashtable();

        private static readonly Hashtable callSites = new Hashtable();

        private static CallSite<Func<CallSite, object, object>> GetCallSiteLocked(string name) {
            var callSite = (CallSite<Func<CallSite, object, object>>)callSites[name];
            if(callSite == null)
            {
                callSites[name] = callSite = CallSite<Func<CallSite, object, object>>.Create(
                            Binder.GetMember(CSharpBinderFlags.None, name, typeof(AccessorCache),
                            new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }));
            }
            return callSite;
        }

        internal static Func<dynamic,object> GetAccessor(string name)
        {
            Func<dynamic, object> accessor = (Func<dynamic, object>)accessors[name];
            if (accessor == null)
            {
                lock (accessors )
                {
                    accessor = (Func<dynamic, object>)accessors[name];
                    if (accessor == null)
                    {
                        if(name.IndexOf('.') >= 0) {
                            string[] props = name.Split('.');
                            CallSite<Func<CallSite, object, object>>[] arr = Array.ConvertAll(props, GetCallSiteLocked);
                            accessor = target =>
                            {
                                object val = (object)target;
                                for (int i = 0; i < arr.Length; i++)
                                {
                                    var cs = arr[i];
                                    val = cs.Target(cs, val);
                                }
                                return val;
                            };
                        } else {
                            var callSite = GetCallSiteLocked(name);
                            accessor = target =>
                            {
                                return callSite.Target(callSite, (object)target);
                            };
                        }
                        accessors[name] = accessor;
                    }
                }
            }
            return accessor;
        }
    }
    public static IOrderedEnumerable<dynamic> OrderBy(this IEnumerable<dynamic> source, string property)
    {
        return Enumerable.OrderBy<dynamic, object>(source, AccessorCache.GetAccessor(property), Comparer<object>.Default);
    }
    public static IOrderedEnumerable<dynamic> OrderByDescending(this IEnumerable<dynamic> source, string property)
    {
        return Enumerable.OrderByDescending<dynamic, object>(source, AccessorCache.GetAccessor(property), Comparer<object>.Default);
    }
    public static IOrderedEnumerable<dynamic> ThenBy(this IOrderedEnumerable<dynamic> source, string property)
    {
        return Enumerable.ThenBy<dynamic, object>(source, AccessorCache.GetAccessor(property), Comparer<object>.Default);
    }
    public static IOrderedEnumerable<dynamic> ThenByDescending(this IOrderedEnumerable<dynamic> source, string property)
    {
        return Enumerable.ThenByDescending<dynamic, object>(source, AccessorCache.GetAccessor(property), Comparer<object>.Default);
    }
    static void Main()
    {
        dynamic a = new ExpandoObject(), b = new ExpandoObject(), c = new ExpandoObject();
        a.X = "abc";
        b.X = "ghi";
        c.X = "def";
        dynamic[] data = new[] { new { Y = a },new { Y = b }, new { Y = c } };

        var ordered = data.OrderByDescending("Y.X").ToArray();
        foreach (var obj in ordered)
        {
            Console.WriteLine(obj.Y.X);
        }
    }
}
215
Ahmed

What is Java equivalent for LINQ?

Answered By: AgileJon ( 206)

There is nothing like LINQ for Java.

214
Nev_Rahd

How can I do GroupBy Multiple Columns in LINQ

Something similar to this in SQL:

SELECT * FROM <TableName> GROUP BY <Column1>,<Column2>

How can I convert this to LINQ:

QuantityBreakdown
(
    MaterialID int,
    ProductID int,
    Quantity float
)

INSERT INTO @QuantityBreakdown (MaterialID, ProductID, Quantity)
SELECT MaterialID, ProductID, SUM(Quantity)
FROM @Transactions
GROUP BY MaterialID, ProductID
Answered By: leppie ( 301)

Use an anonymous type.

Eg

group x by new { x.Column1, x.Column2 }

What is the difference between IQueryable<T> and IEnumerable<T>?

Answered By: Mark Cidade ( 107)

First of all, IQueryable<T> extends the IEnumerable<T> interface, so anything you can do with a "plain" IEnumerable<T>, you can also do with an IQueryable<T>.

IEnumerable<T> just has a GetEnumerator() method that returns an Enumerator<T> for which you can call its MoveNext() method to iterate through a sequence of T.

What IQueryable<T> has that IEnumerable<T> doesn't are two properties in particular—one that points to a query provider (e.g., a LINQ to SQL provider) and another one pointing to a query expression representing the IQueryable<T> object as a runtime-traversable expression that can be understood by the given query provider (for the most part, you can't give a LINQ to SQL expression to a LINQ to Entities provider without an exception being thrown).

The expression can simply be a constant expression of the object itself or a more complex tree of a composed set of query operators and operands. The query provider's IQueryProvider.Execute() or IQueryProvider.CreateQuery() methods are called with an Expression passed to it, and then either a query result or another IQueryable is returned, respectively.

152
stackoverflowuser

what is the difference between returning iqueryable vs ienumerable.

IQueryable<Customer> custs = from c in db.Customers
where c.City == "<City>"
select c;

IEnumerable<Customer> custs = from c in db.Customers
where c.City == "<City>"
select c;

Will both be deferred execution? When should one be preferred over the other?

Answered By: driis ( 268)

Yes, both will give you deferred execution.

The difference is that IQueryable<T> is the interface that allows LINQ-to-SQL (LINQ.-to-anything really) to work. So if you further refine your query on an IQueryable<T>, that query will be executed in the database, if possible.

For the IEnumerable<T> case, it will be LINQ-to-object, meaning that all objects matching the original query will have to be loaded into memory from the database.

In code:

IQueryable<Customer> custs = ...;
// Later on...
var goldCustomers = custs.Where(c => c.IsGold);

That code will execute SQL to only select gold customers. The following code, on the other hand, will execute the original query in the database, then filtering out the non-gold customers in the memory:

IEnumerable<Customer> custs = ...;
// Later on...
var goldCustomers = custs.Where(c => c.IsGold);

This is quite an important difference, and working on IQueryable<T> can in many cases save you from returning too many rows from the database. Another prime example is doing paging: If you use Take and Skip on IQueryable, you will only get the number of rows requested; doing that on an IEnumerable<T> will cause all of your rows to be loaded in memory.

Overview

One of the things I've asked a lot about on this site is LINQ. The questions I've asked have been wide and varied and often don't have much context behind them. So in an attempt to consolidate the knowledge I've acquired on Linq I'm posting this question with a view to maintaining and updating it with additional information as I continue to learn about LINQ.

I also hope that it will prove to be a useful resource for other people wanting to learn about LINQ.

What is LINQ?

From MSDN:

The LINQ Project is a codename for a set of extensions to the .NET Framework that encompass language-integrated query, set, and transform operations. It extends C# and Visual Basic with native language syntax for queries and provides class libraries to take advantage of these capabilities.

What this means is that LINQ provides a standard way to query a variety of datasources using a common syntax.

What flavours of LINQ are there?

Currently there are a few different LINQ providers provided by Microsoft:

There are quite a few others, many of which are listed here.

What are the benefits?

  • Standardized way to query multiple datasources
  • Compile time safety of queries
  • Optimized way to perform set based operations on in memory objects
  • Ability to debug queries

So what can I do with LINQ?

Chook provides a way to output CSV files
Jeff shows how to remove duplicates from an array
Bob gets a distinct ordered list from a datatable
Marxidad shows how to sort an array
Dana gets help implementing a Quick Sort Using Linq

Where to start?

A summary of links from GateKiller's question are below:
Scott Guthrie provides an intro to Linq on his blog
An overview of LINQ on MSDN

ChrisAnnODell suggests checking out:

What do I need to use LINQ?

Linq is currently available in VB.Net 9.0 and C# 3.0 so you'll need Visual Studio 2008 or greater to get the full benefits. (You could always write your code in notepad and compile using MSBuild)

There is also a tool called LinqBridge which will allow you to run Linq like queries in C# 2.0.

Tips and tricks using LINQ

This question has some tricky ways to use LINQ

Answered By: ChrisAnnODell ( 31)

Another good site for Linq is Hooked on Linq and here are 101 Linq samples which are a great reference if you just want a quick syntactical example.

Let's also not forget LinqPad :)