orderby in linq to Entities - asp.net-mvc

AllMovieInfo = from movieInfo in AllMovieInfo
from countryMovie in movieInfo.SeenItWantToSeenIt
where countryMovie.Status==1
select movieInfo;
var seenitorderby = db.SeenItWantToSeeIt.Where(m => m.Status == 1).GroupBy(m => m.MovieID).Select(g => new {MovieID =g.Key,count=g.Count()}).OrderBy(o=>o.count);
List<int> seenItList=seenitorderby.Select(s=>s.MovieID).ToList();
AllMovieInfo = (from a in AllMovieInfo
from s in seenItList
where seenItList.Contains(a.MovieID)
select a).Distinct();
This query is ordering the result according to "AllMovieInfo.MovieID" which is obvious but I have to order the "result" according to the id that comes is "seenitorderby" eg: seen it orderby may take movieID 2,25,7,14,25 then I need AllMovieInfo according same order as seenitorderby .How can I order the "result" according to "seenitorderby " ?

Based on your join aren't AllInfo.ID and SeenInfo.ID the same?
If I'm mistaken the following should do it
var result= (from a in AllInfo
from s in SeenInfo
where s.ID==a.ID
orderby s.ID // <-- this should be the SeenInfo primary key
select a).Distinct();
UPDATE: Based on question update
Thanks for the update. I think I now understand your problem. Do you wish to order by the count for a particular movie...
AllMovieInfo = from movieInfo in AllMovieInfo
from countryMovie in movieInfo.SeenItWantToSeenIt
where countryMovie.Status==1
select movieInfo;
var seenItOrderBy = db.SeenItWantToSeeIt
.Where(m => m.Status == 1)
.GroupBy(m => m.MovieID)
.Select(g => new { MovieID = g.Key, Count=g.Count()});
var result = (from a in AllMovieInfo
from s in seenItOrderBy
where s.MovieID = a.ID
orderby s.Count
select a).Distinct();
You may be able to simplify this as follows...
PLEASE NOTE: This is off the top of my head and based on what I believe you are trying to achive in your code, so please take it as such.
var result = db.AllMovieInfo
// Where someone wants to see it wants to see it
.Where(mi => mi.SeenItWantToSeeIt.Any(m => m.Status == 1))
// Order by number of people that have seen or want to see it
.OrderBy(mi => mi.SeenItWantToSeeIt.Count(m => m.Status == 1));

Related

MVC EF select multiple joins

I have the following DB structure.
I want to make a select using Entity Framework. I want all my Categories that MAY have a CategoryText. If They have a CategoryText I also need to get the Language.
I searched and I couldn't find anything useful.
Here is my query that doesn't work:
var categoriesSQL = db.Categories
.Include(i => i.CategoryTexts.Select(s => s.Language)
.Where(w => w.Format == (string)Session["chosen_language"]));
var categories = categoriesSQL.ToList();
It throws:
The Include path expression must refer to a navigation property defined on the type. Use dotted paths for reference navigation properties and the Select operator for collection navigation properties.
Parameter name: path
I tried to solve this in a lot of ways and recomandations but I couldn't find a solution.
I want the select made in only one query.
Thank you!
Try this
var language = (string)Session["chosen_language"];
var categoriesSQL = db.Categories
.Include(i => i.CategoryTexts.Select(s => s.Language))
.Where(c =>
(from ct in c.CategoryTexts
from l in ct.Languages
select l.Format).Contains(language)
);
var categories = categoriesSQL.ToList();
OR
var language = (string)Session["chosen_language"];
var categoriesSQL = db.Categories
.Include(i => i.CategoryTexts.Select(s => s.Language))
.Where(c => c.CategoryText
.Any(ct => ct.Languages
.Any(l => l.Format == language)
)
);
var categories = categoriesSQL.ToList();

I want take the last 4 record but always get the first 4

I have this in my method:
var qry = db.Forms.Take(4)
.Where(m => m.SateliteID == Id)
.OrderByDescending(m => m.Tanggal)
.ToArray();
What I want is getting the last 4 records from all the records available, but
what I get is the first 4 records.
What I have done wrong?
I thought that command will be the same with this:
SELECT TOP 4 <fields> FROM Forms WHERE sateliteID = Id
ORDER BY tanggal DESC
But it seems they are a different.
What should I do to get what I want (the last 4 records instead of the first 4 records)?
Thanks in advance for the help.
Move your Take:
var qry = db.Forms.Where(m => m.SateliteID == Id)
.OrderByDescending(m => m.Tanggal)
.Take(4)
.ToArray();
var qry = db.Forms.Where(m => m.SateliteID == Id).OrderByDescending(m => m.Tanggal).Take(4).ToArray();
You should order and than take some results from ordered list. Methods should be called in that kind of order.
JUST get apply you where and orderby clause first and than apply take function that will do the work for you
var qry = db.Forms
.Where(m => m.SateliteID == Id)
.OrderByDescending(m => m.Tanggal)
.Take(4)
.ToArray();
For future use :LINQER
this will allow you to convert you SQL QUERIES TO LINQ easily.....very helpful tool

Select object and modify field linq

I have the following Linq Query :
var list = (from user in serviceu.Repository.FindFind(<<filtering nonsense>>)
from profile in serviceP.Repository.GetQuery().Where(p => p.userID == user.userID).DefaultIfEmpty()
select user ).ToList();
Basically i have to add ProfileId to my user entity. Doing this join only lets me select the user element but i want to change the value of user.profileID=profile.profileID ( I have extended the object so it has that field ). How can this be done the fastest way?
I have solved it temporarily by doing this :
var list = (from user in serviceu.Repository.Find(<<filtering nonsense>>)
from profile in serviceP.Repository.GetQuery().Where(p => p.userID == user.userID).DefaultIfEmpty()
select new { user, profile.ProfileID }).ToList();
list.ForEach(el =>
{
el.user.ProfileID = el.ProfileID.ToString();
});
return list.Select(x => x.user).ToList();
Is this the best ( fastest/elegant way )? Can it be done differently?
Instead of ForEach and return try:
return list.Select(c => {c.user.ProfileID = c.ProfileID.ToString(); return c;}).ToList();

Filtering Linq to Entity on Lazy Loading 3 levels Nested Query

Assuming a Entity Framework, in a LazyLoading context.
We have 3 entities:
Product(which has many Order Details)
OrderDetails(which has many Details)
Detail
The following query brings all Products with Name=Books. And to each of these products loads all the OrderDetails which OrderDetail.Quantity>5.
var query = anEntityManager.Products.Where(p => p.Name == "Books")
.Select(p => new { Product = p, OrderDetails = p.OrderDetails.Where(od => od.Quantity > 5) });
var results = query.ToList();
var products = results.Select( x => x.Product);
My Problem is that the Details of each OrderDetail are NOT being retrieved from DB. How can I make an Include in this query so Details are also loaded from DB in the same query?
I think you need to extend your projection:
var query = anEntityManager.Products.Where(p => p.Name == "Books")
.Select(p => new
{
Product = p,
OrderDetails = p.OrderDetails.Where(od => od.Quantity > 5),
Details = p.OrderDetails.Where(od => od.Quantity > 5)
.SelectMany(od => od.Details)
});
var results = query.ToList();
var products = results.Select( x => x.Product);
Using Include in a projection is not supported, so this (a bit ugly) code is the only way I know of to get the result in one database query.
You can probably also use Select instead of SelectMany (Details would then be an IEnumerable<IEnumerable<Detail>> instead of a flat IEnumerable<Detail>) because you are throwing away the projected properties anyway - except the Product property.

LINQ convert DateTime to string

List<Post> list =
(
from c in db.TitleComments
join t in db.Titles on c.TitleId equals t.Id
join u in db.Users on c.UserId equals u.Id
where t.Id == _titleId && c.Date > time
orderby c.Date descending
select new Post { Username = u.Username, PostingDate = c.Date.ToString(), Data = c.Comment }
).ToList();
The code above causes exception on the convertion of date to string, PostingDate = c.Date.ToString(). Any ideas how to get around this?
Exception error:
{"LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expression."}
linq is trying to convert date to string using sql but since there is no ToString() method in sql it can't convert it, this behavior is by design - Joakim
In other words, return the date itself and convert it to a string after it executes on SQL side:
(
select new { Username = u.Username,
PostingDate = c.Date
[...]
})
.ToList() // runs on SQL and returns to the application
.Select(o => // is not generating a SQL, it is running on the app
new Post { Username = o.Username,
PostingDate = o.PostingDate.ToString(),
[...]
})
You can remedy your problem by projecting into an anonymous type, and then at a later step project into Post after the data has already been returned from the DB.
(from ....
select new { /* stuff */, Date = c.Date })
.AsEnumerable()
.Select(p => new Post { /* stuff */, PostingDate = p.Date.ToString() })
.ToList();
However, given that you have a property called PostingDate, the original source being a date, I would recommend your revise your object to actually keep the value as a DateTime instead of a string.
I dont think this can be done in a direct way.
var list =
select new Post { Username = u.Username, PostingDate = SqlFunctions.StringConvert(c.Date), Data = c.Comment }
from
(from c in db.TitleComments
join t in db.Titles on c.TitleId equals t.Id
join u in db.Users on c.UserId equals u.Id
where t.Id == _titleId && c.Date > time
orderby c.Date descending).AsEnumerable()
).ToList();
Also with EF4 you can try something like this:
List<Post> list =
(
from c in db.TitleComments
join t in db.Titles on c.TitleId equals t.Id
join u in db.Users on c.UserId equals u.Id
where t.Id == _titleId && c.Date > time
orderby c.Date descending
select new Post { Username = u.Username, PostingDate = SqlFunctions.DateName(c.Date), Data = c.Comment }
).ToList();

Resources