Linq query select count into same entity - linq

I got two tables: comments and commentLikes
in the same query i count the likes users have given on a comment.
I got the following (simplified) query:
var res = (from c in db.Comments
where c.Topic.ID == topicID
select new
{
comment = c,
count = c.CommentLikes.Count()
}).ToList();
But, rather than mapping the likecount into the comment entity again, I'd like to get a list of Comments only with a field LikeCount in it, preferably with an efficient query. Something like this:
var res = (from c in db.Comments
where c.Topic.ID == topicID
select new
{
comment = c,
c.LikeCount = c.CommentLikes.Count()
}).ToList();
This query doesn't compile.
How to do this in linq?

You can't do that. EF does not support to project (= select) data into an entity. You must fill the LikeCount property in memory after the query has been executed. You can write it in a compact way, but it's basically just a foreach loop over the materialized anonymous objects:
IEnumerable<Comment> res =
(from c in db.Comments
where c.Topic.ID == topicID
select new
{
comment = c,
count = c.CommentLikes.Count()
})
.ToList() // DB query runs here, the rest in memory
.Select(a => {
a.comment.LikeCount = a.count;
return a.comment;
});

Related

How to execute a linq query for each item in a list , use it in the where clause and return a collection from the result of each query?

As you can see I'm executing the query for the first element in the list.
I would like to execute the query for each category in the list and to return one collection with the result of all queries without duplicates (A question can be in multiple categories).
public ObservableCollection<Question> GetQuestionsByCategory(List<Category> categories)
{
var c = categories[0];
var questions = from q in this.Questions where q.Categories.Contains(c)
select q;
return new ObservableCollection<Question>(questions);
}
You could do this:
var questions =
(from c in categories
from q in this.Questions where q.Categories.Contains(c)
select q).Distinct();
But I'd suggest this instead:
var questions = from q in this.Questions
where q.Categories.Any(c => categories.Contains(c))
select q;

Linq to SQL not querying memory

I am using Linq for SQL and have always thought that I was querying the results of a Query in memory. I have just looked at the database and it is showing many thousands of queries rather than 1 which is what I expected.
My approach has been to run a query and then use linq to search within the resultset.
IQueryable<mapping> fieldList = from mm in db.mappings
join mi in db.metaItems on mm.secondaryMetaItemId equals mi.metaItemId
join mo in db.metaObjects on mi.metaObjectId equals mo.metaObjectId
where mm.linkageId == 277
select mm;
for (int i=0;i<100;i++)
{
mapping thisVar = fieldList.FirstOrDefault(m => m.primaryItem == info.Name);
}
How can I stop Linq requerying everytime I access my resultset...
Thanks for your help!
When you write a LINQ query, the query doesn't get actually get executed until you perform an action that actually enumerates over it (deferred execution). Calling FirstOrDefault() is an example of one such method that enumerates over the result (the first result has to be found). You'll want to call a method or otherwise enumerate over the results once. That way when you want to refer to those results throughout your program, you do it on a stored copy.
The easiest way you can do that is to convert it to a list. That will put the results in memory as a list. You could then use that.
IQueryable<mapping> fieldList =
from mm in db.mappings
join mi in db.metaItems on mm.secondaryMetaItemId equals mi.metaItemId
join mo in db.metaObjects on mi.metaObjectId equals mo.metaObjectId
where mm.linkageId == 277
select mm;
// save it!
var result = fieldList.ToList(); // query is processed only once here
// do stuff with result
for (int i=0;i<100;i++)
{
// using the stored result
thisVar = result.FirstOrDefault(m => m.primaryItem == info.Name);
}
try this :
var fieldList = (from mm in db.mappings
join mi in db.metaItems on mm.secondaryMetaItemId equals mi.metaItemId
join mo in db.metaObjects on mi.metaObjectId equals mo.metaObjectId
where mm.linkageId == 277
select mm).AsEnumerable();
foreach (int i=0;i<100;i++)
{
mapping thisVar = fieldList.FirstOrDefault(m => m.primaryItem == info.Name);
}

Filter list having two Tables join data in Entity Framework

I have two tables..
Student (StudentId,Name,FatherName)
Qualification (QualificationId,StudentId,DegreeName)
I have got data like this..
var myList = (from c in entities.Students
join q in entities.Qualifications on c.StudentId equals q.StudentId
select new {c.Name,c.FatherName,q.DegreeName}).ToList();
Now i want to filter myList more.. How can i do it, like..
var filteredList = myList.Select(c=> new Student
{
Name=c.Name,
FatherName=c.FatherName
//Degree=C.Degree
}).ToList();
The above Linq Query is not working if i want to get DegreeName also, My Question is how to further Filter myList.
Thanks.
var filteredList = myList.Where(i => i.FatherName == "Shahid").ToList();
Keep in mind since you called ToList() on the original query you are now filtering in memory. If you want to filter in the database then remove the ToList() on the first query and do it like this:
var myList = from c in entities.Students
join q in entities.Qualifications on c.StudentId equals q.StudentId
select new {
c.Name,
c.FatherName,
q.DegreeName
};
var filteredInDatabase = myList.Where(i => i.FatherName == "Shahid").ToList();

Update class field in LINQ - is it possible?

I have 2 tables, and want to get records from 1 table and to "update" one of its fields from another table, and to pass final list of "Payment" objects somewhere. I cannot use anonymouse type, i need to get the list of proper typed objects.
There was a long way.
Got data:
var paymentsToShow = from p in paymentsRepository.Payments
join r in recordTypeRepository.RecordType
on p.RecordType equals r.Reference into p_r
where p.Customer == CustomerRef
from r in p_r.DefaultIfEmpty()
select new
{
Payment = p,
RecordType = r
};
var objList = paymentsToShow.ToList();
Change required field (basically, Payment.RecordTypeName is empty):
foreach (var obj in objList)
{
obj.Payment.RecordTypeName = obj.RecordType.Name;
}
Got list with correct type:
var paymentsList = from o in objList
select o.Payment;
Is there any way to get code shorter, to make required field update in the query or something else? I dont know where to look for.
I cannot change database.
You could do it like this:
var paymentsToShow = (from p in paymentsRepository.Payments
join r in recordTypeRepository.RecordType
on p.RecordType equals r.Reference into p_r
where p.Customer == CustomerRef
from r in p_r.DefaultIfEmpty()
select new
{
Payment = p,
RecordType = r
}).Select(x =>
{
x.Payment.RecordTypeName = x.RecordType.Name;
return x.Payment;
});
This will result in an IEnumerable<Payment>, so no anonymous type used.

How can I get my orderby to work using an anonymous type?

What do I put in my order by?? I want to order by Name. I have moved the orderby after the distinct because I read that it needs to be done last.
var result = (from r in db.RecordDocs
where r.RecordID == recordID
select new
{
DocTypeID = r.Document.DocType.DocTypeID,
Name = r.Document.DocType.Name,
Number = r.Document.DocType.Number
}
).Distinct().OrderBy( );
Just do
.OrderBy(doc => doc.Name)
Another option, if you really prefer the query expression syntax would be to chain your query construction across multiple statements:
var query = from r in db.RecordDocs
where r.RecordID == recordID
select new
{
DocTypeID = r.Document.DocType.DocTypeID,
Name = r.Document.DocType.Name,
Number = r.Document.DocType.Number
};
query = query.Disctinct();
query = from doc in query orderby doc.Name select doc;
Since all of these methods are deferred, this will result in the exact same execution performance.

Resources