I'm currently having a rough time converting my SQL query to LINQ for a school project I'm using WPF and Entity Framework
here is my SQL query (working exactly as I expect)
select IngrediantName,sum(IngrediantQuantity) as Quantity, IngrediantMeasurementUnit from Users
join Shopping_List
on Users.UserID = Shopping_List.ShoppingListID
join List_Item
on List_Item.ShoppingListID = Shopping_List.ShoppingListID
join Ingrediant
on Ingrediant.IngrediantID = List_Item.IngrediantID
where Users.UserID = 1
group by IngrediantName,IngrediantMeasurementUnit
Here is the query that I have so far
var query = from user in dbContext.Users
join shoppingList in dbContext.ShoppingLists on user.UserId equals shoppingList.UserId
join listItem in dbContext.ListItems on shoppingList.ShoppingListId equals listItem.ShoppingListId
join ingrediant in dbContext.Ingrediants on listItem.IngrediantId equals ingrediant.IngrediantId
where currentUserNumber == user.UserId
select new
{
name = ingrediant.IngrediantName,
quantity = ingrediant.IngrediantQuantity,
unit = ingrediant.IngrediantMeasurementUnit,
};
Here is what i try so far
var query = from user in dbContext.Users
join shoppingList in dbContext.ShoppingLists on user.UserId equals shoppingList.UserId
join listItem in dbContext.ListItems on shoppingList.ShoppingListId equals listItem.ShoppingListId
join ingrediant in dbContext.Ingrediants on listItem.IngrediantId equals ingrediant.IngrediantId
where currentUserNumber == user.UserId
group ingrediant by ingrediant.IngrediantQuantity into x
select new
{
name = x.GroupBy(x => x.IngrediantName),
quantity = x.Sum(x => x.IngrediantQuantity),
unit = x.GroupBy(x => x.IngrediantMeasurementUnit),
};
this one return the following error wiches doesn't tell much
Argument type 'System.Linq.IQueryable1[System.Linq.IGrouping2[System.String,Microsoft.EntityFrameworkCore.Query.TransparentIdentifierFactory+TransparentIdentifier2[Microsoft.EntityFrameworkCore.Query.TransparentIdentifierFactory+TransparentIdentifier2
If someone could point me in the right direction I would appreciate it, if you need more info I will provide it for sure
Thanks
UPDATE
I got this working here the answers to the question for anyone else
var query =
from user in dbContext.Users
join shoppingList in dbContext.ShoppingLists
on user.UserId equals shoppingList.UserId
join listItem in dbContext.ListItems
on shoppingList.ShoppingListId equals listItem.ShoppingListId
join ingrediant in dbContext.Ingrediants
on listItem.IngrediantId equals ingrediant.IngrediantId
where currentUserNumber == user.UserId
group ingrediant by new { name = ingrediant.IngrediantName, unit = ingrediant.IngrediantMeasurementUnit } into x
select new
{
name = x.Key.name,
quantity = x.Sum(x => x.IngrediantQuantity),
unit = x.Key.unit,
};
if you look at the group line
group ingrediant by new { name = ingrediant.IngrediantName, unit = ingrediant.IngrediantMeasurementUnit } into x
from my understanding you use the new to create a new selector then you can use x.key.name and x.key.unit where name and unit are simply some variable
Related
In my asp.net MVC application, view model I have created a property type string to display date.
But in the model, the property is stored as DateTime, so in my query, I have assigned the DateTime by converting it to ToShortDateString.
Because the value stored is with the DateTime in the table.(example2022-10-06 11:32:48.917)
But in the view, I just want to show the Date only.
When running this query I got this error
LINQ to Entities does not recognize the method 'System.String ToShortDateString()' method,
and this method cannot be translated into a store expression.'
Just want to know how to pass only the date to the view of this kind of query.
This is my current code.
var TaskMain = (from t in db.TaskMain
join service in db.Services on t.Service_Id equals service.Id
join category in db.ServiceCategory on service.Service_Category_Id equals category.Id
join branch in db.Branch on t.Current_Branch_Id equals branch.Id
join emp in db.Employee on t.Task_Assigned_Emp_Id equals emp.Id
where t.Id == id
select new TaskDetails
{
Id = t.Id,
Note = t.Note,
Current_Step= t.Task_Step_Id,
Service_Category = category.Service_Category_Name,
Service_End_Date = t.Service_End_Date.ToShortDateString(),
Service_Price = t.Service_Price,
Service_Start_Date = t.CreatedDate.ToShortDateString(),
Task_Created_Branch = branch.BranchName,
Service_Name = service.Service_NameEng
}).ToList();
ToShortDateString() is not something that the database recognize. So you need to bring the conversion to client side by using .AsEnumerable() (or .ToList()). Try this code.
var TaskMain = (from t in db.TaskMain
join service in db.Services on t.Service_Id equals service.Id
join category in db.ServiceCategory on service.Service_Category_Id equals category.Id
join branch in db.Branch on t.Current_Branch_Id equals branch.Id
join emp in db.Employee on t.Task_Assigned_Emp_Id equals emp.Id
where t.Id == id
select new
{
Id = t.Id,
Note = t.Note,
Task_Step_Id= t.Task_Step_Id,
Service_Category_Name = category.Service_Category_Name,
Service_End_Date = t.Service_End_Date,
Service_Price = t.Service_Price,
CreatedDate = t.CreatedDate,
BranchName = branch.BranchName,
Service_NameEng = service.Service_NameEng
}).AsEnumerable()
.Select(t => new TaskDetails
{
Id = t.Id,
Note = t.Note,
Current_Step= t.Task_Step_Id,
Service_Category = t.Service_Category_Name,
Service_End_Date = t.Service_End_Date.ToShortDateString(),
Service_Price = t.Service_Price,
Service_Start_Date = t.CreatedDate.ToShortDateString(),
Task_Created_Branch = t.BranchName,
Service_Name = t.Service_NameEng
}).ToList();
Running into a bit of trouble with my Linq Query. I'm attempting to join several tables and construct a new viewmodel to return to the details page, but running into a bit of a misunderstanding or incorrect syntax.
I have a details page for loads, but I want to include associated data from the trucks table which is joined through a linking table, load_trucks. Below is what I have right now, but is clearly incorrect.
var query = (from l in dbContext.Loads
where l.Id == id
join lt in dbContext.LoadTrucks on l.Id equals lt.LoadId into LoadTrucks
from lt in LoadTrucks.DefaultIfEmpty()
join t in dbContext.Trucks on lt.TruckId equals t.Id into Trucks
where Trucks.All(trk => LoadTrucks.All(ldtrk => ldtrk.TruckId == trk.Id))
from t in Trucks.DefaultIfEmpty()
join u in dbContext.Users on l.UserId equals u.Id into Users
where Users.All(usr => usr.Id == l.UserId)
from u in Users.DefaultIfEmpty()
join u2 in dbContext.Users on l.CreatedBy equals u2.Id into Users2
from u2 in Users2.DefaultIfEmpty()
join dr in dbContext.DriverReceipts on l.Id equals dr.LoadId into DriverReceipts
where DriverReceipts.All(drR => drR.LoadId == l.Id)
from dr in DriverReceipts.DefaultIfEmpty()
join le in dbContext.LogEntries on l.Id equals le.LoadId into LogEntries
where LogEntries.All(lgE => lgE.LoadId == l.Id)
from le in LogEntries.DefaultIfEmpty()
select new LoadsViewModel()
{
Id = l.Id,
LoadId = l.LoadTag ?? l.Id.ToString(),
LoadCreatedBy = u2.FullName,
TruckList = Trucks.ToList(),
UserList = Users.ToList(),
DriverLogEntries = LogEntries.ToList(),
ReceiptList = DriverReceipts.ToList()
});
Any help on this would be great. Thanks!
You need to add :
.FirstOrDefault();
at the end of your query.
That will effectively materialize your query to a single instance of:
LoadsViewModel
You could also wait until the last moment to call .FirstOrDefault() just before where you actually need it.
I have written the following SQL-query that illustrates what I'm trying to achieve:
SELECT
K.id,
SUM(BP.pris)
FROM Kunde K
JOIN Booking BO ON K.id = BO.Kunde_id
JOIN Bane_Booking BB ON BO.id = BB.Booking_id
JOIN Banepris BP ON BO.starttid = BP.time
WHERE BO.gratis = 0
GROUP BY K.id;
Basically it's retrieving the total amount spend by customers. Now I'm trying to convert this query into LINQ, as I'm using LINQ to Entities in my application. This is what I have so far:
from kunde in context.Kunde
join booking in context.Booking on kunde equals booking.Kunde
join banepris in context.Banepris on booking.starttid equals banepris.time
from baneBooking in booking.Bane
select new { Kunde = kunde, Booking = booking, BaneBooking = baneBooking, Banepris = banepris };
I would like however to be able to group these in the same LINQ-query so I dont have to group them manually afterwards. How would i go about achieving this?
I need to get the "kunde"-object and the sum of "banepris.pris".
Without your database, I can't test this, but this should be close:
from K in context.Kunde
join BO in context.Booking on K.id equals BO.Kunde_id
join BP in context.Banepris on BO.starttid equals BP.time
where BO.gratis == 0
group new { Kunde = K, Pris = BP.pris } by K.id into g
select new { ID=g.Key, Kunde = g.First().Kunde, Sum = g.Sum(k=>k.Pris)}
So I have a SQL view that I've created that provides me what I need. Essentially it's a job position billeting system that shows how many positions have been authorized vs filled (or assigned).
SELECT Companies.Name AS Company, Grades.Name AS Grade, Series.Name
AS Series, Positions.Authorized, COUNT(People.PersonId) AS Assigned
FROM Companies INNER JOIN
Positions ON Companies.Id = Positions.CompanyId INNER JOIN
Series ON Positions.SeriesId = Series.Id INNER JOIN
Grades ON Positions.GradeId = Grades.Id INNER JOIN
People ON Positions.CompanyId = People.CompanyId AND
Positions.SeriesId = People.SeriesId AND Positions.GradeId = People.GradeId
GROUP BY Companies.Name, Grades.Name, Series.Name, Positions.Authorized
Now what I'd like to be able to do is recreate this in a LINQ query. I've almost got it where I need it; however, I can't figure out how to add the counted column at the end that's based on the People table.
Here's my current LINQ query:
var query = from a in db.Companies
join b in db.Positions on a.Id equals b.CompanyId
join c in db.Series on b.SeriesId equals c.Id
join d in db.Grades on b.GradeId equals d.Id
join e in db.People on new { b.CompanyId, b.SeriesId, b.GradeId } equals new { e.CompanyId, e.SeriesId, e.GradeId }
group a by new { CompanyName = a.Name, GradeName = d.Name, SeriesName = c.Name, b.Authorized, e.PersonId } into f
select new { Company = f.Key.CompanyName, Grade = f.Key.GradeName, Series = f.Key.SeriesName, f.Key.Authorized, Assigned = /* needs to be Count(People.PersonId) based on last join */ )};
Thanks in advance for any help you can provide!
Figured it out. The reason why it was posting multiple rows and not doing a proper count on the same row was because in my "group by" I added in "e.PersonId" when it should have simply been removed. I also had to add a few things to make it work on the front-end razor views since it's an anonymous type (this doesn't have anything to do with the original question, but thought I'd give reason to the changes). So the person who removed their answer, you were partially right, but the reason it wasn't working was because of the additional fieldin the group by:
dynamic query = (from a in db.Companies
join b in db.Positions on a.Id equals b.CompanyId
join c in db.Series on b.SeriesId equals c.Id
join d in db.Grades on b.GradeId equals d.Id
join e in db.People on new { b.CompanyId, b.SeriesId, b.GradeId } equals new { e.CompanyId, e.SeriesId, e.GradeId }
group a by new { CompanyName = a.Name, GradeName = d.Name, SeriesName = c.Name, b.Authorized } into f
select new { Company = f.Key.CompanyName, Grade = f.Key.GradeName, Series = f.Key.SeriesName, Authorized = f.Key.Authorized, Assigned = f.Count()}).AsEnumerable().Select(r => r.ToExpando());
And what it looks like on the page:
I would like to use my entity class properties in my linq query that return some value with it.
so this my linq query;
List<PvmBarChartData> BaseofSegmentIPPGMR = (from si in db.ScoreItem
join s in db.Score on si.ScoreId equals s.Id
join prg in db.ProjectResearchGroup on si.ProjectResearchGroupId equals prg.Id
join rg in db.RgClone on prg.RgCloneId equals rg.Id
join sp in db.SalesPoint on s.SalesPointId equals sp.Id
join c in db.Channel on sp.ChannelId equals c.Id
where (si.ResearchGroupType == ResearchGroupType.ScoreCard && spIds.Contains(s.SalesPointId))
group si by c.Name into g
select new PvmBarChartData
{
GroupName = g.Key,
DataValues = new List<CvmNameValuePair>{ new CvmNameValuePair{
Name = "",
Value = g.Average(x => x.TotalScore)
}
}
})
.ToList();
so for instance I would like to set Name properties with my entity framework model class' properties' value, Name = s.Name,
How can I implement this on my code?
A way that you can access s.Name is by doing another linq query on g, since g is now a data set of grouped objects.
Name = (from gx in g select gx.Name).FirstorDefault();