What's the equivalent of GROUP INTO in Linq extension method? - linq

This is how I'm filtering and grouping transTasks.
var transTasks = from t in taskData
where t.RangeName == rName
group t by t.CultureID into g
select new { language = g.Key, tasks = g };
Now I've a new requirement. Depending on the conditions, I'may filter by RangeName or by TaskOrderId.
That's why I've transformed the above Linq code to the following;
var transTasks = taskData
.Where(predicate)
.GroupBy(???)
.Select(???);
I've researched but I can't still find the equivalent of group into for the extension method. I need to group those transTasks because there is a loop inside another loop.
Thanks for helping

GroupBy is the equivalent , and it seems you have figured it out, your query in Method Syntax would be:
var transTrasks = taskData.Where(t => t.RangeName == rName)
.GroupBy(t => t.CultureID)
.Select(g => new { language = g.Key, tasks = g });
As a side note, Any LINQ query in query expression compiles to Method Syntax.

var transTasks = taskData
.Where(predicate)
.GroupBy(t => t.CultureID)
.Select(g => new { language = g.Key, tasks = g });

Related

Co-related Queries using lambda expressions

How can I convert this LINQ query from query syntax to method syntax? I am performing a co-related query operation.
var query = (from r in objEntities.Employee
where r.Location == (from q in objEntities.Department
where q.Location == r.Location
select q.Location).FirstOrDefault()
select new
{
FirstName = r.FirstName,
LastName = r.LastName,
Age = r.Age,
Location = r.Location
});
GridView1.DataSource = query;
GridView1.DataBind();
I think you are trying to convert the query to method-based query instead of syntax-based query.
var query = objEntities.Employee
.Where(e => e.Location == objEntities.Department
.Where(d => d.Location == r.Location)
.Select(d => d.Location)
.FirstOrDefault())
.Select(e => new {
FirstName = e.FirstName,
LastName = e.LastName,
Age = e.Age,
Location = e.Location
});
I'm also pretty sure your inner expression within where clause could be replaced with something like that:
.Where(e => objEntities.Department.Any(d => d.Location == e.Location)
Nested queries always have performance issue instead you should use join:
In the lambda expression query should be
var query = objEntities.Employee.Join(objEntities.Department, E => E.Location,
D => D.Location,
(E,D) => new {
FirstName = E.FirstName,
LastName = E.LastName,
Age = E.Age,
Location = E.Location
});

Trim whitespace from DataTable cells with Linq

This piece of code works to trim all spaces in each datacell of each datarow.
How can I get this code:
var dataRows = dataTable.AsEnumerable();
foreach (var row in dataRows)
{
var cellList = row.ItemArray.ToList();
row.ItemArray = cellList.Select(x => x.ToString().Trim()).ToArray();
}
into one line of code so I don't have to loop through each row? Something like this but it doesn't work:
dataTable.AsEnumerable().Select(y => y.ItemArray.ToList()).Select(x => x.ToString().Trim());
If you love LINQish stype:
dataTable.AsEnumerable().ToList()
.ForEach(row =>
{
var cellList = row.ItemArray.ToList();
row.ItemArray = cellList.Select(x => x.ToString().Trim()).ToArray();
});
With linq you can't change item values finally you should run for loop (or foreach) to change fields value.
for example
var iq = obj from dataTable.asEnumerable() select new{
PersonName = a.Field<string>("PersonName"),
PersonID = a.Field<decimal>("PersonID"),
ParticipantString = a.Field<string>("DisplayString"),
PersonUserName = d.Field<string>("UserName")
}

How to rewrite it more efficiently (linq with split)?

here is the problem:
I have a column with the topics in the format: "boston | new york | chicago". The names can be different and number of the topics can vary in the records.
What I need to come up with is the collection of the same names with the count of those names.
This is what I have done:
var splitted = queryResult.Select(x => x.TopicData);
List<string> lstOfTopics = new List<string>();
foreach (var element in splitted)
{
string[] splitedTopics = element.Split('|');
lstOfTopics.AddRange(splitedTopics);
}
var groupedTopics = lstOfTopics.GroupBy(x => x).Select(group => new {key = group.Key, count = group.Count()}).AsEnumerable();
seems a lot of code for a simple task. any ideas how to simplify this?
thanks!
You can construct the list using SelectMany and ToList:
List<string> lstOfTopics = splitted.SelectMany(x => x.Split('|')).ToList();
You can also omit the construction of the list entirely:
var groupedTopics = queryResult
.SelectMany(x => x.TopicData.Split('|'))
.GroupBy(x => x)
.Select(group => new { group.Key, Count = group.Count()});
var groups = queryResult
.SelectMany(t => t.TopicData.Split('|')
.GroupBy(n => n)
.Select(g => new { Key = g.Key, Count = g.Count() });
query syntax can be nice and compact:
var topics =
from qr in queryResult
from topic in qr.TopicData.Split('|')
group topic by topic into g
select new { Topic = g.Key, Count = g.Count() };
If you want just the unique topics, but not their counts...
List<string> topicList = topics.Select(item => item.Topic);

Dynamic Where clauses with multiple joins using Linq

I need to build a dynamic where clause in a Linq statement with multiple joins.
.Net 3.5
Linq-To-Sql
I have these incoming parameters for the Linq statement, only the "UID" is required.
int uid = 23702; // <-- Only one Required
string courseNumber = "";
string title = "";
int? categoryId = null;
int? typeId = null;
I've been testing this out in LinqPad and while I've gotten the query to work with all Where clauses in place, the Nullable int parameters end up returning incorrect results.
Here's my Linq statement:
var ci = course_instances;
var query = courses.Join(ci,
c => c.course_id,
i => i.course_id,
(c, i) => new
{
c = c,
i = i
}).Join(user_courses,
temp => temp.i.instance_id,
uc => uc.instance_id,
(temp, uc) => new
{
temp = temp,
uc = uc
})
.Where (temp1 => (temp1.uc.uid == uid))
.Where (temp1 => (temp1.temp.c.course_number.Contains(courseNumber)))
.Where (temp1 => (temp1.temp.c.title.Contains(title)))
//.Where (temp1 => (temp1.temp.c.course_type_id == typeId))
//.Where (temp1 => (temp1.temp.c.course_category_id == categoryId))
.Select (temp1 => new CourseSearchMyCourses
{
// snipped the many properties
});
I've tried using PredicateBuilder, but it returns the error:
The type arguments for method 'System.Linq.Queryable.Where(System.Linq.IQueryable, System.Linq.Expressions.Expression>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Here's my PredicateBuilder Linq attempt:
var conditions = PredicateBuilder.True<user_course>();
conditions = conditions.And(c => c.uid == uid);
var ci = course_instances;
var query = courses.Join(ci,
c => c.course_id,
i => i.course_id,
(c, i) => new
{
c = c,
i = i
}).Join(user_courses,
temp => temp.i.instance_id,
uc => uc.instance_id,
(temp, uc) => new
{
temp = temp,
uc = uc
})
.Where (conditions)
.Select (temp1 => new CourseSearchMyCourses
{
// snipped the many properties
});
BTW, I also tried using "System.Linq.Dynamic" using string queries, and got the error the " and " isn't recognized.
Any help is appreciated.
Thanks.
Linq predicates with nullable type variables get translated into a SQL predicate = NULL. But that is totally different than what it should be: IS NULL.
You expect to get the rows where course_type_id is empty, but the = comparison returns no results because NULL is not a value and the comparison returns UNKNOWN. I think that is the cause of your "incorrect results".
If this is your problem, a fix can be found here.

LINQ: Group By + Where in clause

I'm trying to implement a T-SQL equivalent of a where in (select ...) code in LINQ.
This is what I have now:
int contactID = GetContactID();
IEnumerable<string> threadList = (from s in pdc.Messages
where s.ContactID == contactID
group 1 by new { s.ThreadID } into d
select new { ThreadID = d.Key.ThreadID}).ToList<string>();
var result = from s in pdc.Messages
where threadList.Contains(s.ThreadID)
group new { s } by new { s.ThreadID } into d
let maxMsgID = d.Where(x => x.s.ContactID != contactID).Max(x => x.s.MessageID)
select new {
LastMessage = d.Where(x => x.s.MessageID == maxMsgID).SingleOrDefault().s
};
However, my code won't compile due to this error for the ToList():
cannot convert from
'System.Linq.IQueryable<AnonymousType#1>'
to
'System.Collections.Generic.IEnumerable<string>'
Anyone have any suggestions on how to implement this? Or any suggestions on how to simplify this code?
Your query returns a set of anonymous types; you cannot implicitly convert it to a List<string>.
Instead, you should select the string itself. You don't need any anonymous types.
Change it to
var threadList = pdc.Messages.Where(s => s.ContactID == contactID)
.Select(s => s.ThreadID)
.Distinct()
.ToList();
var result = from s in pdc.Messages
where threadList.Contains(s.ThreadID)
group s by s.ThreadID into d
let maxMsgID = d.Where(x => x.ContactID != contactID).Max(x => x.MessageID)
select new {
LastMessage = d.Where(x => x.MessageID == maxMsgID).SingleOrDefault()
};

Resources