Reputation: 1611
I am learning LINQ. Can anybody please help me to solve the following problem!
From Northwind's Customers and Orders tables:
I want to "Find all Customers who have done more than 20 Orders"
The Query in SQL Server for the same is:
SELECT * FROM Customers WHERE CustomerID in (SELECT CustomerID FROM Orders GROUP BY CustomerID HAVING COUNT(CustomerID) > 20)
But, I could not able to write the equivalent in LINQ.
I have tried like below:
var customers = ctx.Customers.Where(o => o.CustomerID.Count() > 20).GroupBy(o => o.CustomerID);
I am geting the following error in Event Log:
Exception information: Exception type: HttpCompileException Exception message: e:\Ashok\WEB\VS2012\CSHWEB\CSHWEB\LINQ01.aspx(17): error CS0103: The name 'Orders' does not exist in the current context
The reason is that the dependent Orders table might not be loaded yet. But, I am not understanding how to make it work!
Upvotes: 1
Views: 1559
Reputation: 9116
In order to write to such query, you need to use a database relation (Navigation Property). This relation should be declared in your context as Customer.Orders
. After then, you can use Linq to query the context.
Check this out for an example which describes what you need.http://msdn.microsoft.com/en-us/library/bb425822.aspx
However you can declare context like:
public partial class Northwind : DataContext
{
public Table<Customer> Customers;
public Table<Order> Orders;
public Northwind(string connection): base(connection) {}
}
and you should define your Customer class like:
[Table(Name="Customers")]
public class Customer
{
[Column(Id=true)]
public string CustomerID;
...
private EntitySet<Order> _Orders;
[Association(Storage="_Orders", OtherKey="CustomerID")]
public EntitySet<Order> Orders {
get { return this._Orders; }
set { this._Orders.Assign(value); }
}
}
then you can query it like the other answers said.
Upvotes: 1
Reputation: 13381
try use join..into clause something like this
var customers = from c in ctx.Customers
join o in ctx.Orders on c.CustomerID equals o.CustomerID into orders
where orders.Count()>20
select c;
Upvotes: 1
Reputation: 6260
Your relations between objects should be properly configured. If you're using Entity Framework just mark Orders
property in Customers
entity as virtual
this will allow lazy loading. Then your query will be much simpler. Otherwise you can still start from Orders
instead of Customers
:
var customers = ctx.Orders.GroupBy(c => c.CustomerID)
.Where(x => x.Count() > 20)
.SelectMany(g => g.Select(o => o.Customer));
And for customers (with virtual
Orders collection) pretty straightforward:
var customers = ctx.Customers.Where(c => c.Orders.Count() > 20);
Upvotes: 1
Reputation: 2201
You could do something like this:
var customers = from c in Customers where c.Orders.Count() > 20 select c;
customers.GroupBy(o => o.CustomerID);
Upvotes: 1
Reputation: 1963
If customers and orders are related (1:MANY) and you have set up your object model to reflect this you could do:
var customers = ctx.Customers.Where(c => c.Orders.Count() > 20);
If not then:
var customerIds = ctx.Orders.GroupBy(x => x.CustomerID)
.Where(x => x.Count() > 20);
.SelectMany(x => x.CustomerID);
var customers = ctx.Customers.Where(x => customerIds.Contains(x.CustomerID));
Upvotes: 1