MVC EF select multiple joins - asp.net-mvc

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();

Related

Asp.net MVC 3 Dropdown List Database Population remove item

I have a dropdown list where it is populated from the database I want to remove an a number from the options list. This is the code
var id= ctx.tableMaster.Select(x => x.id).Where(x != "0").Distinct();
What would I put in the were statement to check if the idis not equal to 0
Thanks
Is id an integer? If so, you don't need quotes:
var idList = ctx.tableMaster.Where(x => x.id != 0).Select(x => x.id).Distinct();
You could try this too
var results = ctx.tableMaster.FindAll(x => !x.id.Equals(0));
If you have to ignore multiple ids
List<int> ignoreIds = new List<int>() { 0, 1, 5, 9};
var results = ctx.tableMaster.FindAll(x => !ignoreIds.Contains(x.id));

orderby in linq to Entities

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));

Joining of two queries and returning in list format

I am developing a MVC application.
I am using the two queries to fetch the record, and I want to get the common records from these queries .
I want to return the data set in list
Like this
return Json(poList, JsonRequestBehavior.AllowGet);
My two queries are..
var poList = (from po in db.PurchaseOrders
where po.CompanyId == companyId && po.PartyId == partyId && (po.IsDeleted == false || po.IsDeleted == null)
select po into newPO
select new
{
Name = newPO.PONo,
Id = newPO.Id
});
//.ToList().OrderBy(e => e.Name);
var poList2 = (db.Employees.Where(x => x.Id == EmpID)
.SelectMany(x => x.Roles)
.SelectMany(x => x.Employees)
.Distinct()
.SelectMany(x => x.PurchaseOrders)
.Select(po => new { Name = po.PONo, Id = po.Id }));
var finalPO = from PO in poList.ToList().Union(poList2).ToList() select PO);
The reason you can't union them is that the two lists return different objects.
The first list returns an anonymous type with members Name and Id. If, instead, you just wanted to return the purchase orders in query one, then you could simply use the following:
var poList = (
from po in db.PurchaseOrders
where po.CompanyId == companyId &&
po.PartyId == partyId &&
(po.IsDeleted == false || po.IsDeleted == null)
select po
);
You may need to append .ToList() to the query above in order to use the Union(...) method. Then, you should be able to union the two sequences together (assuming poList2 is also a sequence of db.PurhaseOrders objects.
Conversely, instead of changing query for poList above, you could change the query behind poList2 to the following to achieve the same effect, but different results:
var poList2 = (db.Employees.Where(x => x.Id == EmpID)
.SelectMany(x => x.Roles)
.SelectMany(x => x.Employees)
.Distinct()
.SelectMany(x => x.PurchaseOrders)
.Select(po => new { Name = po.PONo, Id = po.Id }));
Personally, I think the first one is more clear (unless there are many fields on the PO object and you only need the two as shown).
UPDATE: I see the original post was edited so that both queries now return the same object (or shape of object). However, the poster is still trying to combine the results incorrectly. The poster is using yet another LINQ query in an attempt to use the Union(...) method. This is completely unnecessary. Might as well write out the code for him/her:
var finalPO = poList.Union(poList2).ToList(); // ToList() only necessary if you need a list back
That should do it.
Really, the two books I mentioned in my comments below will get you a long way in understanding .NET and LINQ: APress - Pro C# and the .NET Framework 4.0; O'Reilly - C# 5 in a Nutshell. There are also many books on LINQ alone--but without a solid grasp of .NET (and C#, F#, or VB), you can't hope to understand or use LINQ.
I dont not think you need the ToList() in the intermediate results, just use the union and do the ToList in the final result, like:
var finalPO = poList.Union(poList2).ToList()
First, create a ViewModel like this:
public class PurchaseOrderViewModel
{
public int Id { get; set; }
public string Name { get; set; }
}
Then, use it in your code like this:
var poList1 = (from po in db.PurchaseOrders
where po.CompanyId == companyId && po.PartyId == partyId
&& (po.IsDeleted == false || po.IsDeleted == null)
select po into newPO
select new PurchaseOrderViewModel
{
Name = newPO.PONo,
Id = newPO.Id
}).ToList();
var poList2 = (db.Employees.Where(x => x.Id == EmpID)
.SelectMany(x => x.Roles)
.SelectMany(x => x.Employees)
.Distinct()
.SelectMany(x => x.PurchaseOrders)
.Select(po => new PurchaseOrderViewModel
{
Name = po.PONo,
Id = po.Id
})).ToList();
var finalList = poList1.Union(poList2);

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

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.

Resources