Bind Distinct LINQ query to Telerik grid - asp.net-mvc-3

I'm trying to bind a LINQ query that has a Distinct() in it and bind it to a Telerik Grid (this is the Telerik grid still, haven't converted to Kendo yet). I've tried adding AsQueryable() to it also, but still getting a "Specified method is not supported exception."
My query looks like this:
var rewardTypes = (from type in _rewardTypeRepository.GetAll()
from vo in type.ValidOutlets
join ot in _outletRepository.GetAll()
on vo.Outlet.Id equals ot.Id
where userOutletIds.Contains(ot.Id)
select vo.RewardType).Distinct().AsQueryable();
Any ideas or guidance on this would be greatly appreciated.
Thank you,
Matt

Using .Distinct() or IQueryable<T> just lazy loads the collection of data, meaning it's not actually enumerated yet.
Try converting it to a List<T>.
var rewardTypes = (from type in _rewardTypeRepository.GetAll()
from vo in type.ValidOutlets
join ot in _outletRepository.GetAll()
on vo.Outlet.Id equals ot.Id
where userOutletIds.Contains(ot.Id)
select vo.RewardType).ToList();
If you want to remain "light" and not enumerate every item in a potentially large collection, I suggest using the .Skip() and .Take() methods to paginate through results at your convenience. Both those methods work against an IQueryable<T> collection.

Related

Query syntax for getting a list as a list of different types?

I have a query that fetches books, I'm new to LINQ so I don't know the syntax:
var books = (from book in db.Books
join borrow in db.Borrows on book equals borrow.Book
select new BookDTO { Title = book.Title,
Borrows = book.Borrows.ToList() }).ToList(); // book.Borrows.ToList() <- use dto's instead
How can I select Book.Borrows as a list of objects (BorrowDTO's)? Is there something like Borrows = new List<BorrowDTO>(book.Borrows)
You can use .Select() to project the list into a different type. So instead of this:
Borrows = book.Borrows.ToList()
you would have something like this:
Borrows = book.Borrows.Select(b => new BorrowDTO { /* properties here */ }).ToList()
Note that, depending on your data source, there may be more efficient ways to approach selecting your data. If you're pulling directly from LINQ To Entities then you may run into problems trying to materialize a type within the query that isn't known to the DB, or any other operation that can't be translated into SQL. It's also not necessarily wise to toss in a bunch of .ToList() operations without a specific purpose.
But that's all theoretical at this point in the question. Based on the code shown and on LINQ syntax itself, you can select from a list just fine. (I'd even recomment using the extension method syntax more than the query syntax that you currently use. Personal preference of course, but I find it easier and more intuitive to build nested operations like this. Though you can just as well use the from ... select ... syntax after Borrows =, I would imagine.)
Just select book.Borrows instead of creating a new temporal object.
That query is going to return a IEnumerable of the Borrows type; and you'll be able to iterate through it and convert it into a List if you please

How can I get the IQueryable object used by LinqDataSource?

Is there a way to get the IQueryable object that the LinqDataSource has used to retrieve data? I thought that it might be possible from the selected event, but it doesn't appear to be.
Each row in my table has a category field, and I want to determine how many rows there are per category in the results.
I should also note that I'm using a DataPager, so not all of the rows are being returned. That's why I want to get the IQueryable, so that I can do something like
int count = query.Where(i => i.Category == "Category1").Count();
Use the QueryCreated event. QueryCreatedEventArgs has a Query property that contains the IQueryable.
The event is raised after the original LINQ query is created, and contains the query expression before to it is sent to the database, without the ordering and paging parameters.
There's no "Selected" event in IQueryable. Furthermore, if you're filtering your data on the server, there'd be no way you can access it, even if the API exposed it, but to answer a part of the question, let's say you have category -> product where each category has many products and you want the count of the products in each category. It'd be a simple LINQ query:
var query = GetListOfCategories();
var categoryCount = query.Select(c => c.Products).Count();
Again, depending on the type of object GetListOfCategories return, you might end up having correct value for all the entries, or just the ones that are loaded and are in memory, but that's the different between Linq-to-Objects (in memory) and Linq-to-other data sources (lazy loaded).

Best way to use LINQ query & Gridview paging when dealing with large recordsets.

I have a gridview on a page which is populated by a LINQ query in the code behind. Nothing fancy but, does use pagination (using the pageIndex changed event).
All works fine but, ran into a problem when running in our dev environment due to there being alot of data in the DB.
So my question is given that the LINQ is only enumerated on databinding and the gridview has a page size of 20, does the LINQ fetch all of the records each time its databound?
and how would you deal with binding the results of a LINQ query to a gridview when dealing with a large number of records?
Here is the solution in which I have created the custom grid whcih support linq query and paginging : LINQ TO SQL GridView (Enhanced Gridview)
I suggest using two methods:
Get the current page of results you want to view by using the Skip() and Take() methods on the IQueryable<T> result set. You would pass in your pageIndex and maximumRows values to determine the value to send into Skip() (e.g. pageIndex * maximumRows).
The second method to use is to get the count of total possible records using the Count() method on the same exact LINQ query. This way you can get the count without getting all the rows (massive amounts of data).
Hope that helps.

Shaping EF LINQ Query Results Using Multi-Table Includes

I have a simple LINQ EF query below using the method syntax. I'm using my Include statement to join four tables: Event and Doc are the two main tables, EventDoc is a many-to-many link table, and DocUsage is a lookup table.
My challenge is that I'd like to shape my results by only selecting specific columns from each of the four tables. But, the compiler is giving a compiler is giving me the following error:
'System.Data.Objects.DataClasses.EntityCollection does not contain a definition for "Doc' and no extension method 'Doc' accepting a first argument of type 'System.Data.Objects.DataClasses.EntityCollection' could be found.
I'm sure this is something easy but I'm not figuring it out. I haven't been able to find an example of someone using the multi-table include but also shaping the projection.
Thx,Mark
var qry= context.Event
.Include("EventDoc.Doc.DocUsage")
.Select(n => new
{
n.EventDate,
n.EventDoc.Doc.Filename, //<=COMPILER ERROR HERE
n.EventDoc.Doc.DocUsage.Usage
})
.ToList();
EventDoc ed;
Doc d = ed.Doc; //<=NO COMPILER ERROR SO I KNOW MY MODEL'S CORRECT
DocUsage du = d.DocUsage;
Very difficult to know what is going on without a screencap of your model, including the navigational properties on each entity.
But if your saying it's a many-to-many between Event and Doc (with EventDoc being the join table), and assuming your join table has nothing but the FK's and therefore doesn't need to be mapped, then shouldn't a single Event have many Doc's?
This query:
var query = ctx.Event.Include("EventDoc.Doc");
Would imply (based on the lack of pluralization): a single Event has a single EventDoc which has a single Doc.
But shouldn't that be: a single Event has a single EventDoc which has many Doc's.
Therefore your projection doesn't really make sense. Your trying to project to an anonymous type, with EventDate and Filename for a single Doc, but an Event has many Docs.
Maybe a projection like this would be more suitable:
var query = ctx.Event.Include("EventDoc.Docs.DocUsage")
.Select(x => new
{
EventDate = x.EventDate,
DocsForEvent = x.EventDocs.Docs
}).ToList();
And for that you work you need to fix up your model. Im surprised it even validates/compiles.
Either your model is wrong or your description of the database cardinalities in your question is. :)
Of course, i could be completely misunderstanding your database and/or model - so if i am let me know and i'll remove this answer.

Outer Joins with Subsonic 3.0

Does anyone know of a way to do a left outer join with SubSonic 3.0 or another way to approach this problem? What I am trying to accomplish is that I have one table for departments and another table for divisions. A department can have multiple divisions. I need to display a list of departments with the divisions it contains. Getting back a collection of departments which each contain a collection of divisions would be ideal, but I would take a flattened result table too.
Using the LINQ syntax seems to be broken (I am new to LINQ though and may be using it wrong), for example this throws an ArgumentException error:
var allDepartments = from div in Division.All()
join dept in Department.All() on div.DepartmentId equals dept.Id into divdept
select divdept;
So I figured I could fall back to using the SubSonic query syntax. This code however generates an INNER JOIN instead of an OUTER JOIN:
List<Department> allDepartments = new Select()
.From<Department>()
.LeftOuterJoin<Division>(DepartmentsTable.IdColumn, DivisionsTable.DepartmentIdColumn)
.ExecuteTypedList<Department>();
Any help would be appreciated. I am not having much luck with SubSonic 3. I really enjoyed using SubSonic 2 and may go back to that if I can't figure out something as basic as a left join.
Getting back a collection of departments which each contain a collection of divisions would be ideal
SubSonic does this for you (if you setup your relationships correctly in the database), just select all Departments:
var depts = Model.Department.All();
There will be a property in each item of depts named Divisions, which contains a collection of Division objects.

Resources