How do I convert this query into LINQ?
Here employeeList is a list of employees(model) and idList has a list of ids(int).
Update employeeList
Set employeeList.CaseNumber = '100'
where employeeList.id in idList
It is not possible to create a LINQ-Query that will result in the given UPDATE query.
The only solution is to iterate through the collection of items and set the CaseNumber to 100.
foreach(var item in context.employeeList.Where(i => idList.Contains(i.id))
{
item.CaseNumber = "100";
}
context.SaveChanges();
But this will result in n queries send to the database.
A better solution is to execute the query directly to the database.
context.Database.SqlQuery("UPDATE ... SET ... WHERE");
Another possibility would be to use StoredProcedures which are then mapped to the ORM.
If I understood properly, you only need a LINQ alternative to what you wrote.
If that is the case please try the provided code
employeeList.Where(x => idList.Contains(x.id)).ToList().ForEach(i => i.CaseNumber = 100);
Related
I want to group by a datatable by the columns which are present in a List. Moreover I want to sum a column using group by result.
How to create a dynamic linq query for this?
In case you want to use a dynamic linq query for this, you can use System.Linq.Dynamic.Core.
The code could look like:
var result = context.Posts.GroupBy("BlogId").Select("new(Key, Sum(NumberOfReads) AS TotalReads)");
See also
https://dynamic-linq.net/basic-query-operators#groupby-by-a-single-key-and-do-a-sum
Just group by the identifier you need and then sum the column as below.
var lstYourClass = lstYourClass .GroupBy(x => x.Id).Select(z => new YourClassType
{
Amount= z.Sum(a => a.Amount),
}).ToList();
Hope it helps :)
I have a linq query which seems to be reversing one column of several in some rows of an earlier query:
var dataSet = from fb in ds.Feedback_Answers
where fb.Feedback_Questions.Feedback_Questionnaires.QuestionnaireID == criteriaType
&& fb.UpdatedDate >= dateFeedbackFrom && fb.UpdatedDate <= dateFeedbackTo
select new
{
fb.Feedback_Questions.Feedback_Questionnaires.QuestionnaireID,
fb.QuestionID,
fb.Feedback_Questions.Text,
fb.Answer,
fb.UpdatedBy
};
Gets the first dataset and is confirmed working.
This is then grouped like this:
var groupedSet = from row in dataSet
group row by row.UpdatedBy
into grp
select new
{
Survey = grp.Key,
QuestionID = grp.Select(i => i.QuestionID),
Question = grp.Select(q => q.Text),
Answer = grp.Select(a => a.Answer)
};
While grouping, the resulting returnset (of type: string, list int, list string, list int) sometimes, but not always, turns the question order back to front, without inverting answer or questionID, which throws it off.
i.e. if the set is questionID 1,2,3 and question A,B,C it sometimes returns 1,2,3 and C,B,A
Can anyone advise why it may be doing this? Why only on the one column? Thanks!
edit: Got it thanks all! In case it helps anyone in future, here is the solution used:
var groupedSet = from row in dataSet
group row by row.UpdatedBy
into grp
select new
{
Survey = grp.Key,
QuestionID = grp.OrderBy(x=>x.QuestionID).Select(i => i.QuestionID),
Question = grp.OrderBy(x=>x.QuestionID).Select(q => q.Text),
Answer = grp.OrderBy(x=>x.QuestionID).Select(a => a.Answer)
};
Reversal of a grouped order is a coincidence: IQueryable<T>'s GroupBy returns groups in no particular order. Unlike in-memory GroupBy, which specifies the order of its groups, queries performed in RDBMS depend on implementation:
The query behavior that occurs as a result of executing an expression tree that represents calling GroupBy<TSource,TKey,TElement>(IQueryable<TSource>, Expression<Func<TSource,TKey>>, Expression<Func<TSource,TElement>>) depends on the implementation of the type of the source parameter.`
If you would like to have your rows in a specific order, you need to add OrderBy to your query to force it.
How I do it and maintain the relative list order, rather than apply an order to the resulting set?
One approach is to apply grouping to your data after bringing it into memory. Apply ToList() to dataSet at the end to bring data into memory. After that, the order of subsequent GrouBy query will be consistent with dataSet. A drawback is that the grouping is no longer done in RDBMS.
I have some duplicate values in my database so I am using Linq to Entity to remove them with the code below. The problem is that there is an autonumber primary key in RosterSummaryData_Subject_Local, which invalidates the line var distinctRows = allRows.Distinct();
So, even if all the rows are the same, distinct won't work because the pk is different. Is there anyway to discredit the pk in the distinct? Or anyway to remove it from the query so it becomes a non issue. Just to note I want the query to return an IQueryable of my entity type so I can use the RemoveRange() method on the enttiy to remove the duplicates.
var allRows = (from subjLocal in customerContext.RosterSummaryData_Subject_Local
select subjLocal);
var distinctRows = allRows.Distinct();
if (allRows.Count() == distinctRows.Count())
{
return;
}
else
{
var rowsToDelete = allRows.Where(a => a != distinctRows);
customerContext.RosterSummaryData_Subject_Local.RemoveRange(rowsToDelete);
}
EDIT
I realized that to properly bring back distinct rows, all I have to do is select all the items except primary key:
var distinctRows = allRows
.Select(a => new {a.fkRosterSetID, a.fkTestInstanceID, a.fkTestTypeID,
a.fkSchoolYearID, a.fkRosterTypeID, a.fkDistrictID,
a.fkSchoolID, a.fkGradeID, a.fkDepartmentID,
a.fkCourseID, a.fkPeriodID, a.fkDemoCommonCodeID,
a.fkDemoCommonCategoryID, a.fkTest_SubjectID})
.Distinct();
The problem is that I cannot fetch the duplicate rows with the code below because the ! operator does not work with anonymous types(the variable distinctRows is an anonymous type because I didn't select all the columns):
var rowsToDelete = allRows.Where(a => a != distinctRows);
Any help?
you can try this:
var allRows = (from subjLocal in customerContext.RosterSummaryData_Subject_Local
select subjLocal).ToList();
var distinctRows = allRows.Distinct().ToList();
Since you will be dealing with list objects, then in your original else statement you can do this:
else
{
var rowsToDelete = allRows.Where(a => !distinctRows.Contains(a));
customerContext.RosterSummaryData_Subject_Local.RemoveRange(rowsToDelete);
}
To handle your issue with Distinct() and the autonumberID in the database, there are two solutions I can think of.
One is you can bring in the MoreLinq library, it's a Nuget package. then you can use the MoreLinq method DistinctBy():
allRows.DistinctBy(a => a.SomePropertyToUse);
Or the other route would be to use an IEqualityComparer with the regular .Distinct() Linq Method. You can check out this SO question for more info on using an IEqualityComparer in the .Distinct() method. using distinct with IEqualityComparer
maybe you need to check for each one of the fields in your customerContext.RosterSummaryData_Subject_Local to see which one is different
The database contains Orders.
Orders can be contained within a group of Orders.
For every group of Orders it could contain 1 to many Orders.
However, Orders could have a NULL value assigned GroupOrderId as previous Orders did not have the grouping concept. Only new Orders enforce the concept of being added to a group.
The class structure to be populated in order to perform actions on each Order is
public class OrdersGroup
{
public int? GroupOrderId { get; set; }
public List<int> OrderIds { get; set; }
}
The linq statement
var workPacketOrdersList = (from o in db.Orders
where
o.GroupOrderId >= groupOrderIdMin && o.GroupOrderId <= groupOrderIdMax &&
o.IsDeleted == false
orderby o.WorkPacketId ascending
group o by o.WorkPacketId
into grp
select new OrdersGroup
{
GroupOrderId = grp.Key,
OrderIds = grp.Select(g => g.OrderId).ToList()
}).ToList();
Full exception
LINQ to Entities does not recognize the method 'System.Collections.Generic.List`1[System.Int32] ToList[Int32](System.Collections.Generic.IEnumerable`1[System.Int32])' method, and this method cannot be translated into a store expression.
I see that the returned type of the linq query is a List<OrdersGroup>.
If the final .ToList() is omitted from the query than the return type becomes an IQueryable<OrdersGroup>
No matter what action is performed next the result is an exception that this method cannot be translated into a store expression.
I have tried to remove the specific select new OrdersGroup into a more generic select new and then perform actions on this result only to find the same store expression exception.
Can someone give some insight into where this linq is incorrect?
this is the part that's failing - grp.Select(g => g.OrderId).ToList() - you can't have a .ToList() in the select clause. remove that and you should be fine.
The problem is that LINQ to Entities is attempting to convert your query into SQL. It doesn't know how translate ToList into SQL, so that's the problem. You need to remove the call to ToList from inside your query.
That is,
OrderIds = grp.Select(g => g.OrderId).ToList()
LINQ to Entities can not convert that to SQL. Remove the call
OrderIds = grp.Select(g => g.OrderId)
and if you need OrderIds to be a List<int>, do the call to ToList after you execute the query.
It's because you're trying to call ToList() in a part of the query that will become raw SQL and executed at the source (ie SQL Server, not the CLR). I don't know exactly what your data is so I can't necessarily make an accurate recommendation on how to fix it but I would try taking making the ToList() call after this query or just not making it all. It's likely IEnumberable will offer whatever functionality you need which is what the Select will return if you remove the ToList() call.
By the way since I wasn't explicit, I'm referring to the ToList() call inside the select -(second to last line) OrderIds = grp.Select(g => g.OrderId).ToList() the other one is fine. It's executed on the results of the SQL query which is perfectly fine, you just can't make calls to C# specific methods within a query that will be executed by the SQL provider.
Your problem is that you select a list in your select statement.
select new OrdersGroup
{
GroupOrderId = grp.Key,
OrderIds = grp.Select(g => g.OrderId).ToList()
/////////////////////////////////////^^^^^^^^^HERE
}
What you need to do is change OrderIds to an IEnumerable<int>, and then get rid of the ToList.
i have a query which gets records from the database,
i need to pass ids in parameters to call this function,
like Myfunction(1, 2, 3)
i want to get the results which matching with this ids,
like
public List<Items> GetItems(int[] ids)
{
var a = from Items in db.item
where items.id == ids[]
select new Items
{
}
return a.ToList();
}
there is confusion on where clause ( how to get records regarding provided its)
i tried this with looping the ids but could not get any success
Thanks in Advance
You may use Contains, method to check. Something similar to Select * from table where Ids in (1,2,3,...)
Try the following.
var a = from item in db.Items
where ids.Contains(item.id)
select new Item {.....}
Where ids is your array.
You may see: Creating IN Queries With Linq To Sql
change your code to the following
public List<Items> GetItems(int[] ids)
{
var a = from Items in db.item
where ids.Contains(Items.id)
select new Items
{
}
return a.ToList();
}