I have 3 tables
- ERPEntry
- ERPEntryType
- ERPApp
I am trying to get data from these 3 tables using the below query but i got the error :
specified linq expression contains references to queries that are
associated with different contexts
var erpEntryInfo = (from s in ERPDB.ERPEntrys
JOIN t in ERPDB.ERPEntryTypes
on s.EntryTypeID equals t.EntryTypeID
join a in APPDB.ERPApps
on s.AppId equals a.AppId
where s.UserIDAdded == '250176'
select new ERPInfo
{
EntryId = s.EntryID,
EntryType = t.EntryTypeName,
ERPApp = a.ApplicationName,
DateAdded = s.DateAdded
}).OrderByDescending(d => d.DateAdded).Take(10).ToList();
I searched based on the errror and tried to split the above query into 2 as below.
var res = (from s in ERPDB.ERPEntrys
join t in ERPDB.ERPEntryTypes
on s.EntryTypeID equals t.EntryTypeID
where s.UserIDAdded == '250176'
select new {s.EntryTypeID, s.DateAdded, t.EntryTypeName, s.AppID }).OrderByDescending(d => d.DateAdded).Take(10).ToArray();
var y = (from a in APPDB.ERPApps
join b in res on a.AppId equals //??//
select new ERPInfo
{
EntryId = b.EntryID,
EntryType = b.EntryTypeName,
ERPApp = a.ApplicationName,
DateAdded = b.DateAdded
}).ToList();
I am having an issue in the above query to access AppId which i got into the result res..i commented with //??// in the above code
can i get any help on this.
Related
Here I have SQL query, now I am trying to translate it into linq but don't have any idea how to do it and got stuck in getting ChapterId from ChapterQuestion table.
Any help with translation will be grate.
Thank you
Below is my sql query
SELECT CQ.ChapterId,CQS.SetNumber,count(distinct CQ.ChapterQuestionId) as questioncount FROM
[dbo].[ChapterQuestion] AS CQ
JOIN [dbo].[ChapterQuestionSet] AS CQS ON CQ.ChapterQuestionSetId = CQS.ChapterQuestionSetId
WHERE CQ.ChapterId = 1 group by CQS.SetNumber,CQ.ChapterId
Below is my linq
var list = (from CQS in uow.Repository<ChapterQuestionSet>().GetAll().ToList()
join CQ in uow.Repository<ChapterQuestion>().FindBy(x => x.ChapterId == chapterId).ToList()
on CQS.ChapterQuestionSetId equals CQ.ChapterQuestionSetId
group CQ by CQS into G1
select new ChapterQuestionSetVM
{
ChapterQuestionSetId = G1.Key.ChapterQuestionSetId,
Count = G1.Count(t => t.ChapterQuestionSetId != null),
QuestionSetNo = $"Question set {G1.Key.SetNumber}",
ChapterId = // how do i get chapterid from ChapterQuestion
}).ToList();
This is corrected query. I hope Repository.GetAll() returns IQueryable?
This query works only with EF Core 5.x
var query =
from CQS in uow.Repository<ChapterQuestionSet>().GetAll()
join CQ in uow.Repository<ChapterQuestion>().GetAll() on CQS.ChapterQuestionSetId equals CQ.ChapterQuestionSetId
where CQ.ChapterId == 1
group CQ by new { CQS.SetNumber, CQ.ChapterId } into G1
select new ChapterQuestionSetVM
{
ChapterId = G1.Key.ChapterId
QuestionSetNo = $"Question set {G1.Key.SetNumber}",
Count = G1.Select(t => t.ChapterQuestionSetId).Distinct().Count(),
};
var list = query.ToList();
I have this semi-complex query that counts the most voted user post of the last 7 days:
var fromDate = dateTimeService.Now.Add(-interval);
var votedPosts =
from vote in dbContext.Votes
join post in dbContext.Posts on vote.PostId equals post.PostId
group new {vote.Sign, post.PostId} by post.PostId
into postVotes
select new {
PostId = postVotes.Key,
TotalRating = postVotes.Sum(pv => pv.Sign)
};
var bestPost = (
from post in dbContext.Posts
join votedPost in votedPosts on post.PostId equals votedPost.PostId
join room in dbContext.Rooms on post.RoomId equals room.RoomId
join game in dbContext.Modules on room.ModuleId equals game.ModuleId
where room.RoomAccess == RoomAccessType.Open && post.CreateDate > fromDate
orderby votedPost.TotalRating descending,
post.CreateDate descending
select new BestPost
{
UserId = post.UserId,
ModuleId = game.ModuleId,
ModuleTitle = game.Title,
PostId = post.PostId,
PostText = post.Text,
PostCommentary = post.Commentary,
PostCreateDate = post.CreateDate,
TotalRating = bestPost.TotalRating
}).FirstOrDefault();
What I try to do here is to group user votes by PostId, sum the evaluations of their votes by field Sign (can be -1, 0 or 1), then join it with some additional data like game Id/Title and post texts, filter non-public or too old posts, then order it by rank and then by create date, then map it onto DTO and return the very first result if present.
All the fields here are simple basic types: the Vote.Sign is int, Post.CreateDate is DateTime, all the *Id are Guid and Text/Title/Commentary are string.
I get the warning:
warn: Microsoft.EntityFrameworkCore.Query[20500]
The LINQ expression 'orderby [bestPost].TotalRating desc' could not be translated and will be evaluated locally.
warn: Microsoft.EntityFrameworkCore.Query[20500]
The LINQ expression 'FirstOrDefault()' could not be translated and will be evaluated locally.
If I remove the sort by TotalRating and only leave the CreateDate sorting, it works fine, creates proper LIMIT request. But with TotalRating the query looks like this:
SELECT
t."PostId", t."TotalRating", post."CreateDate" AS "PostCreateDate",
post."UserId", game."ModuleId", game."Title" AS "ModuleTitle",
post."PostId" AS "PostId0", post."Text" AS "PostText",
post."Commentary" AS "PostCommentary"
FROM
"Posts" AS post
INNER JOIN
(SELECT
post0."PostId", SUM(vote."Sign")::INT AS "TotalRating"
FROM
"Votes" AS vote
INNER JOIN
"Posts" AS post0 ON vote."PostId" = post0."PostId"
GROUP BY
post0."PostId") AS t ON post."PostId" = t."PostId"
INNER JOIN
"Rooms" AS room ON post."RoomId" = room."RoomId"
INNER JOIN
"Modules" AS game ON room."ModuleId" = game."ModuleId"
WHERE
(room."RoomAccess" = 0) AND (post."CreateDate" > #__fromDate_0)
And it looks pretty bad to be calculated in dotnet runtime.
I tried to wrap the result in another select from, but it didn't help. I also cannot do the group by on all the columns because then I won't be able to aggregate things like ModuleId because EF Core 2.2 does not support the group.FirstOrDefault things and PostgreSQL does not support max(uuid) (otherwise I could use group.Max(g => g.ModuleId)).
What am I doing wrong?
What happens if you combine the gist of votedPosts into the query so you don't duplicate the join on posts?
var bestPost = (
from post in dbContext.Posts
join vote in dbContext.Votes on post.PostId equals vote.PostId into votej
let voteTotalRating = votej.Sum(pv => pv.Sign)
join room in dbContext.Rooms on post.RoomId equals room.RoomId
join game in dbContext.Modules on room.ModuleId equals game.ModuleId
where room.RoomAccess == RoomAccessType.Open && post.CreateDate > fromDate
orderby voteTotalRating descending,
post.CreateDate descending
select new BestPost {
UserId = post.UserId,
ModuleId = game.ModuleId,
ModuleTitle = game.Title,
PostId = post.PostId,
PostText = post.Text,
PostCommentary = post.Commentary,
PostCreateDate = post.CreateDate,
TotalRating = voteTotalRating
}).FirstOrDefault();
I am using LINQ query to get the rows with certain conditions. Here is the query.
var query = from v in dt1.AsEnumerable()
join c in dt2.AsEnumerable() on v.Field<int>("ID") equals c.Field<int>("ID")
where v.Field<string>("col1").Equals("abcd")
&& (c.Field<string>("col1").Equals("8776") || c.Field<string>("col1").Equals("8775"))
select new
{
ok = (from a in v where v.Field<string>("stah").Equals("1") select a).count(),
ok1 = (from a in v where v.Field<string>("stah").Equals("2") select a).count(),
ok2 = (from a in v where v.Field<string>("stah").Equals("3") select a).count()
};
The error is present in
ok = (from a in v where v.Field<string>("stah").Equals("1") select a).count()
The error is
could not find an implementation of the query pattern for source type
'system.data.DataRow'. 'Where' not found
Sample Input :
dt1
iD col1 stah
1 4567 1
2 8748 2
3 3487 3
4 8776 1
dt2
iD col1
1 4754
2 4576
Output
Get count of all rows where stah=1 && dt2.col1='4754'
But I cannot get it working. What is the correct syntax for this ?
If I have understood you correctly, then this is what you need:-
var query = dt1.AsEnumerable()
.Where(x => x.Field<int>("stah") == 1
&& dt2.AsEnumerable()
.Any(z => z.Field<int>("Id") == x.Field<int>("Id")
&& z.Field<string>("Col1") == "4754")
).Count();
#HarshitShrivastava mentioned that my previous attempt at the query didn't take into account all the where conditions.
How about this version using a mix of Linq query and Linq Lambda:
var query = from dataRows1 in dt1.AsEnumerable().Where(r => r.Field<string>("col1").Equals("abcd"))
join dataRows2 in dt2.AsEnumerable().Where(r => r.Field<string>("col1").Equals("8776") || r.Field<string>("col1").Equals("8775"))
on dataRows1.Field<int>("ID") equals dataRows2.Field<int>("ID") into b
select new
{
id = dataRows1.Field<int>("ID"),
ok = (from a in b where a.Field<string>("stah").Equals("1") select a).Count(),
ok1 = (from a in b where a.Field<string>("stah").Equals("2") select a).Count(),
ok2 = (from a in b where a.Field<string>("stah").Equals("3") select a).Count()
};
Note: I included the ID field in the projected output just for verifying the results. Remove as needed.
I am able to write this code for a Web Api. In this code i have written tow queries and combined both in a way that comments and follower data should be merged (not combined) with respect to time based on ctime and startedfollowing. If a user has a new comment, the comment should come first and if the follower is first, the follower data should come first.
public IQueryable<Object> GetCommentsandFollowActivityCommnets()
{
var combo1 = from c in db.comments
join p in db.picturedetails on c.targetpictureid equals p.idpictures
join u in db.users on c.iduser equals u.iduser
select new TCommentDTO
{
idcomments=c.idcomments,
comment1 = c.comment1,
targetpictureid = c.targetpictureid,
ctime = c.ctime,
iduofpic=p.iduser,
iduofcommentor=c.iduser,
profilepicofcommentor=u.profilepic,
usernameofcommentor=u.username,
picFilename=p.picFilename,
picTitle=p.picTitle
};
var combo2= from f in db.followers
join u in db.users on f.iduser equals u.iduser
select new TfollowerDTO
{
idfollowers=f.idfollowers,
iduser=f.iduser,
targetiduser=f.targetiduser,
startedfollowing=f.startedfollowing,
unoffollower=u.username,
ppoffollower=u.profilepic,
status=u.status
};
var result1 = from c in combo1
select new UserTimeLineDTO
{ SortKey = c.ctime, Member =c};
var result2 = from c in combo2
select new UserTimeLineDTO{ SortKey = c.startedfollowing, Member = c };
var result = result1.Concat(result2).OrderBy(x =>x.SortKey).Select(x => x.Member);
return result;
}
The code is not giving any compile time error. It runs fine in compiler, but on run time i am getting an exception:
DbUnionAllExpression requires arguments with compatible collection ResultTypes.
How to remove this exception?
As a workaround, I would try to evaluate the last expression in memory:
var result1 = (from c in combo1
select new UserTimeLineDTO
{ SortKey = c.ctime, Member =c}).ToList();
var result2 = (from c in combo2
select new UserTimeLineDTO{ SortKey = c.startedfollowing, Member = c }).ToList();
var result = result1.Concat(result2).OrderBy(x =>x.SortKey).Select(x => x.Member);
The union should now succeed, as well as ordering and the final projection.
I'm trying to convert this very simple piece of SQL to LINQ:
select * from Projects p
inner join Documents d
on p.ProjectID = d.ProjectID
left join Revisions r
on r.DocumentID = d.DocumentID
and r.RevisionID IN (SELECT max(r2.RevisionID) FROM Revisions r2 GROUP BY r2.DocumentID)
WHERE p.ProjectID = 21 -- Query string in code
This says, if any revisions exist for a document, return me the highest revision ID. As it's a left join, if not revisions exist, I still want the results returned.
This works as expected, any revisions which exist are shown (and the highest revision ID is returned) and so are all documents without any revisions.
When trying to write this using LINQ, I only get results where revisions exist for a document.
Here is my attempt so far:
var query = from p in db.Projects
join d in db.Documents on new { ProjectID = p.ProjectID } equals new { ProjectID = Convert.ToInt32(d.ProjectID) }
join r in db.Revisions on new { DocumentID = d.DocumentID } equals new { DocumentID = Convert.ToInt32(r.DocumentID) } into r_join
from r in r_join.DefaultIfEmpty()
where
(from r2 in db.Revisions
group r2 by new { r2.DocumentID }
into g
select new { MaxRevisionID = g.Max(x => x.RevisionID) }).Contains(
new { MaxRevisionID = r.RevisionID }) &&
p.ProjectID == Convert.ToInt32(Request.QueryString["projectId"])
select new { d.DocumentID, d.DocumentNumber, d.DocumentTitle, RevisionNumber = r.RevisionNumber ?? "<No rev>", Status = r.DocumentStatuse == null ? "<Not set>" : r.DocumentStatuse.Status };
I'm not very good at LINQ and have been using the converter "Linqer" to help me out, but when trying I get the following message:
"SQL cannot be converted to LINQ: Only "=" operator in JOIN expression
can be used. "IN" operator cannot be converted."
You'll see I have .DefaultIfEmpty() on the revisions table. If I remove the where ( piece of code which does the grouping, I get the desired results whether or not a revision exists for a document or not. But the where clause should return the highest revision number for a document IF there is a link, if not I still want to return all the other data. Unlike my SQL code, this doesn't happen. It only ever returns me data where there is a link to the revisions table.
I hope that makes a little bit of sense. The group by code is what is messing up my result set. Regardless if there is a link to the revisions table, I still want my results returned. Please help!
Thanks.
=======
The code I am now using thanks to Gert.
var query = from p in db.Projects
from d in p.Documents
where p.ProjectID == Convert.ToInt32(Request.QueryString["projectId"])
select new
{
p.ProjectID,
d.DocumentNumber,
d.DocumentID,
d.DocumentTitle,
Status = d.Revisions
.OrderByDescending(rn => rn.RevisionID)
.FirstOrDefault().DocumentStatuse.Status,
RevisionNumber = d.Revisions
.OrderByDescending(rn => rn.RevisionID)
.FirstOrDefault().RevisionNumber
};
gvDocumentSelection.DataSource = query;
gvDocumentSelection.DataBind();
Although this works, you'll see I'm selecting two fields from the revisions table by running the same code, but selecting two different fields. I'm guessing there is a better, more efficient way to do this? Ideally I would like to join on the revisions table in case I need to access more fields, but then I'm left with the same grouping problem again.
Status = d.Revisions
.OrderByDescending(rn => rn.RevisionID)
.FirstOrDefault().DocumentStatuse.Status,
RevisionNumber = d.Revisions
.OrderByDescending(rn => rn.RevisionID)
.FirstOrDefault().RevisionNumber
Final working code:
var query = from p in db.Projects
from d in p.Documents
where p.ProjectID == Convert.ToInt32(Request.QueryString["projectId"])
select new
{
p.ProjectID,
d.DocumentNumber,
d.DocumentID,
d.DocumentTitle,
LastRevision = d.Revisions
.OrderByDescending(rn => rn.RevisionID)
.FirstOrDefault()
};
var results = from x in query
select
new
{
x.ProjectID,
x.DocumentNumber,
x.DocumentID,
x.DocumentTitle,
x.LastRevision.RevisionNumber,
x.LastRevision.DocumentStatuse.Status
};
gvDocumentSelection.DataSource = results;
gvDocumentSelection.DataBind();
If you've got 1:n navigation properties there is a much simpler (and recommended) way to achieve this:
from p in db.Projects
from d in p.Documents
select new { p, d,
LastRevision = d.Revisions
.OrderByDescending(r => r.RevisionId)
.FirstOrDefault() }
Without navigation properties it is similar:
from p in db.Projects
join d in db.Documents on new { ProjectID = p.ProjectID }
equals new { ProjectID = Convert.ToInt32(d.ProjectID) }
select new { p, d,
LastRevision = db.Revisions
.Where(r => d.DocumentID = Convert.ToInt32(r.DocumentID))
.OrderByDescending(r => r.RevisionId)
.FirstOrDefault() }
Edit
You can amend this very wide base query with all kinds of projections, like:
from x in query select new { x.p.ProjectName,
x.d.DocumentName,
x.LastRevision.DocumentStatus.Status,
x.LastRevision.FieldA,
x.LastRevision.FieldB
}