views:

44

answers:

1

I'm quite a newbie in EF, so I'm sorry if my question has been answered before.. I just can't figure out the syntax..

I have two entities, Category & Product, where one category has many products.

I want to get all categories, with only their latest product (it has a date property named timestamp)

I have no idea how to do that. :-/

If possible I'd like to know the syntax of the two ways to write it, both the sql-like syntax, and the C# like syntax, e.g.:

ctx.Categories.Include("Products").ToList() 

from c in ctx.Categories.Include("Products")

Thanks!

A: 

Here's the SQL-like way:

var categories =
        from p in products
        group p by p.Category into g
        select new { Category = g.TheKey, LatestProduct = g.Max(p => p.TimeStamp) };

This is the Lambda-way (warning, untested):

var categories = products.GroupBy(p => p.Category)
                         .Select(g => new { Category = g.TheKey, 
                                            LatestProduct = g.Max(p => p.TimeStamp)});

A note on Categories.Include("Products"), you don't need this in your example. You use "Include" for eager-loading, so that for example if you had a list of Categories returned from EF, when you do Categories.Product you will get the associated product.

But all you require is a list of categories, and a single product for each one - which is already returned in the above LINQ query, so no need for Include.

RPM1984
Thanks! However, turns out I actually need something a bit different - I am working with Ria Services, so my method has to return IQueriable<Cateogry> and what you're returning here is an anonymous type (which is very restrictive to begin with - you can't really return that type from a method..) Can u plz supply me with a method that returns a list of categories, and for each category, the Products property would only contain the latest product? And while we're on the subject - is this the way to go? or should I add another Property to the Category? Thanks!
EdotK
My answer was just an example for how to write the query, obviously you need to apply that to whatever scenario you have. :) Just change the projection from an anonymous type to the Category: `select new Category { Product = g.Max(p => p.TimeStamp) };`
RPM1984
and returning an IQueryable is a totally different beast. what's the point of returning an IQueryable list of Categories if you have already filtered/max'd the products? If you're returning an IQueryable, you should just return db.Categories (that's it), and the above code should be done where you want to project the IQueryable to a concrete collection - such as a service layer.
RPM1984
Are you familiar with WcfRiaServices (it's for silverlight)? u have to return IQueriable by default. It doesn't really return that - it's a shortcut to allow u to add filters on the client side. Just to make sure, if i want to put the selected product into the products property (there is no product property ofcourse), how would i do that? again, thank you very much :)
EdotK
I don't have much knowledge in WCF RIA/SL, i focus on ASP.NET :) Okay so a "Category" object doesn't have a "Product" property? Then either add it to the Category object, or return some other object which does have it.
RPM1984
That is what I'm going to do, but again, my EF knowledge is horrible, so I'm just wondering how can I put the product into the Products property of Category. It's probably very very simple and I am going to buy a book about EF (do u have any recommandations btw?) but if u could show me the syntax for that it would be great :)
EdotK
Im confused by what your issue is. can you not do this: `select new Category { Product = g.Max(p => p.TimeStamp) };` ? That will assign the latest product (by timestamp) to the 'Product' property of the 'Category' (assuming a Category entity has a Product property). As i said in my first comment above.
RPM1984
WRT books - i'm reading "Programming Entity Framework Second Edition" by Julia Lerman at the moment. Very good, extreme detail (914 pages)
RPM1984
the category has a productS property, not product (plural).
EdotK
and thanks for the book ref, i just ordered it on amazon :)
EdotK
Right. In that case, something like this should work: `select new Category { Products = { new { g.Max(p => p.TimeStamp) } } };` This is not a EF/LINQ thing. You have a property called "Products" (IEnumerable<Product>, ICollection<Product>, etc), you need to add a single "Product" to the collection.
RPM1984