I have written some LINQ but it doesn't return the correct data, it seems to ignore my where clause. Can anybody advise me on what I am doing wrong with the syntax?
IEnumerable<Ranking> lst = (from r in results
join m in membersToRank on r.UserId equals m.userId
join t in teamsToRank on m.teamId equals t.teamId
where r.ResultDate >= rankingStart
&& r.ResultDate <= rankingEnd
select new Ranking
{
memberId = m.memberId,
chain = t.chain,
name = m.name,
teamId = m.teamId,
value = results.Count(i => i.IsCorrect && i.UserId == m.userId)
}).ToList();
This line
value = results.Count(i => i.IsCorrect && i.UserId == m.userId)
will bypass the where clause. You have have to repeat the where there
value = results.Where(...).Count(i => i.IsCorrect && i.UserId == m.userId)
or
var results2 = results.Where(...)
and then use only results2.
(as a sidenote, it will even bypass the join, so it could become a little more complex depending on what you want)
Related
The following is my code that works. But as you can see I am having to write select twice
var lstCargoRequestVM =
(from c in db.Cargo
join v in db.Vehicles on c.VehicleID equals v.VehicleID
join cmp in db.Companies on c.CompanyID equals cmp.CompanyID
where c.Isdeleted == false && c.IsActive == true
select new CargoRequestVM
{
CargoId = c.CargoID,
CompanyName = cmp.CompanyName,
VehicleNo = v.VehicleNo,
Date = c.DateOfPassage,
Type = c.Type.ToString()
})
.AsEnumerable()
.Select(x => new CargoRequestVM
{
CargoId = x.CargoId,
CompanyName = x.CompanyName,
VehicleNo = x.VehicleNo,
Date = x.Date,
Type = CargoElements.CargoTypeName(x.Type.ToString())
}).ToList();
Is it possible to do the same without having to write select twice? There could be more than a dozen properties in certain case. I don't want to make my code unnecessarily lengthy.
Probably that wouldn't have a translation to underlying database and thus you need to write basically twice. However you can apply the AsEnumerable() after where using method syntax like (assuming you in fact have a good relational schema defined and navigational properties set - in Linq you very rarely need join keyword):
stVM = db.Cargo
.Include( c => c.Vehicle )
.Include( c => c.Company )
.Where( c => !c.Isdeleted && c.IsActive )
.AsEnumerable()
.Select( c => new CargoRequestVM
{
CargoId = c.CargoID,
CompanyName = c.Company.CompanyName,
VehicleNo = c.Vehicle.VehicleNo,
Date = c.DateOfPassage,
Type = CargoElements.CargoTypeName(c.Type.ToString())
}).ToList();
I write query about search about specific employee but did'nt work ,I know there is an error in my query but did'nt now where it.
I have 2 tables one for company and another for employee info.
the progress will be:
1'st Query search in company table by department number and company
number then get the PK_companyID .
2'ed JOIN company.PK_companyID==employee.FK_companyID.
3'ed Query will search in employee table by FK_companyID when the
name enter will be the same in employee table.
I hope its Clear to understand
var query = (from c in db.Company
where c.departmentNO== departmentNumber && c.companyNo==companyNumber
join x in db.Employee c.PK_companyID==x.FK_companyID
where (x.FirstName.Contains(firstName ?? x.FirstName)
&& x.SecondName.Contains(secondName ?? x.SecondName)
&& x.ThirdName.Contains(thirdName ?? x.ThirdName)
&& x.FourthName.Contains(fourthName ?? x.FourthName))
select x).ToList();
Thank in advance.
You can simplify your query and your filtering by using code such below, should also result much cleaner SQL if you are not using all your filters.
var employees = (from c in db.Company
join e in db.Employee on c.PK_companyID equals e.FK_companyID
where c.departmentNO == departmentNumber && c.companyNo == companyNumber
select e);
if (!String.IsNullOrEmpty(firstName))
employees = employees.Where(pr => pr.FirstName.Contains(firstName));
if (!String.IsNullOrEmpty(secondName))
employees = employees.Where(pr => pr.SecondName.Contains(secondName));
if (!String.IsNullOrEmpty(thirdName))
employees = employees.Where(pr => pr.ThirdName.Contains(thirdName));
if (!String.IsNullOrEmpty(fourthName))
employees = employees.Where(pr => pr.FourthName.Contains(fourthName));
return employees.ToList();
var query = (from c in db.Company
join x in db.Employee c.PK_companyID == x.FK_companyID
where c.departmentNO == departmentNumber && c.companyNo == companyNumber
&& (x.FirstName.Contains(firstName ?? x.FirstName)
&& x.SecondName.Contains(secondName ?? x.SecondName)
&& x.ThirdName.Contains(thirdName ?? x.ThirdName)
&& x.FourthName.Contains(fourthName ?? x.FourthName))
select x).ToList();
You should use keyword "equals" instead of "==" in join as below:
var query = (from c in db.Company
join x in db.Employee c.PK_companyID equals x.FK_companyID
where c.departmentNO == departmentNumber && c.companyNo == companyNumber
.......
Hope this will work.
I am trying to exclude items that have a.id that exists in db.AdminAdjusterStatus.
from u in db.Users
join a in db.Adjusters on u.id equals a.userID
where u.userType.ToLower() == "adjuster"
&& !(from x in db.AdminAdjusterStatus select x.adjusterID).Contains(a.id)
select new AdjusterProfileStatusItem { user = u, adjuster = a }
The code above says, "where NOT contains a.id in db.AdminAdjusterStatus.adjusterID.
The problem is, it doesn't work. I have these two entries in db.AdminAdjusterStatus:
A9EC05B5-651D-4AA7-8275-1F6BFE212C03
1BDE55D9-ED0A-4854-9D5F-B89DB17F02D2
And, the LINQ query gives me:
A9EC05B5-651D-4AA7-8275-1F6BFE212C03
1BDE55D9-ED0A-4854-9D5F-B89DB17F02D2
e21ff49c-9505-495d-b4a3-c259ee3459d6
Whereas, it should only give me:
e21ff49c-9505-495d-b4a3-c259ee3459d6
var query = from u in db.Users
from a in db.Adjusters
where u.userType.ToLower() == "adjuster" &&
u.id == a.userID &&
!db.AdminAdjusterStatus.Any(i => i.adjusterID == a.id)
...
You could try doing a Left Join and filtering on the null records. Without having data to test against I cannot say for certain on if it will work "out of the box" but I have used the following code several times for doing filtering like this:
db.Users.Join(db.Abjusters, outer => outer.id, inner => inner.userID, new { User = outer, Adjuster = inner })
.GroupJoin(DBConcurrencyException.AdminAdjusterStatus, outer => outer.Adjuster.id, inner => inner.adjusterID, new { User = outer.User, Adjuster = outer.Adjuster, Admins = inner })
.SelectMany(grp => grp.Admins.DefaultIfEmpty(), (grp, admin) => new { User = grp.User, Adjuster = grp.Adjuster, Admin = admin })
.Where(item => item.User.userType == "adjuster" && item.Admin == null)
.Select(item => new AdjusterProfileStatusItem { user = item.User, adjuster = item.Adjuster });
The GroupJoin/SelectMany combination performs a Left Join and then you can filter where the object is null which should produce the same as a NOT IN.
Thanks to everyone for their help and sorry to waste anyone's time. I realized that this line:
obj.adjusterID = '#(Url.RequestContext.RouteData.Values["id"])';
Elsewhere in my code had been sending u.id instead of a.id as I had thought that it was. Because of this, I was saving the wrong ID in my database, thus resulting in the problem I was experiencing.
Thanks, again for all your help!
Perhaps this could work?
var AdjusterItems = from aa in AdminAdjusterStatus
join a in Adjusters
on aa.AdjusterId equals a.AdjusterId
select a.UserId;
var UsersNotAdjustAdmin = from u in Users
where !AdjusterItems.Any(x => x == u.Id)
&& u.UserType.Equals("Adjuster", StringComparison.InvariantCultureIgnoreCase)
select u;
var result = from u in UsersNotAdjustAdmin
join a in Adjusters
on u.Id equals a.UserId
select new AdjusterProfileStatusItem() { Adjuster = a, User = u };
here is my linq code:
BOOK entity = db.BOOKS
.Where(s => s.ID == (from p in db.LIBRARY
from b in db.BOOKS
where (p.ID == 123) && (p.idpage == b.idpage)
select b.fields));
My actual oracle code is:
SELECT DISTINCT BOOKS.ID
FROM LIBRARY,BOOKS
WHERE LIBRARY.ID = 123 AND LIBRARY.ID = BOOKS.ID
But its showing the error in s.ID that..
Delegate 'System.Func Project.Models.BOOKS,int,bool' does not take 1 arguments
Why does this happen? Are there any workarounds?
Your SQL is using a join, so you can do the same thing in LINQ. Either of these approaches will suffice:
// join
var query = (from b in db.BOOKS
join p in db.LIBRARY on b.IdPage equals p.IdPage
where p.ID == 123
select b.Id).Distinct();
// 2 from statements (SelectMany) can also be used as a join
var query = (from b in db.BOOKS
from p in db.LIBRARY
where p.ID == 123 && b.IdPage == p.IdPage
select b.Id).Distinct();
// fluent syntax
var query = db.BOOKS
.Where(b => db.LIBRARY.Any(p =>
p.ID == 123 && b.IdPage == p.IdPage))
.Select(b => b.Id)
.Distinct();
s.ID is comparing to an Enumerable, so you get the error.
At the end of the LINQ query, add a SingleOrDefault().
Your subquery returns a sequence of values, not a single values, so you can't compare it to a scalar property like ID. You should use First on the result of the subquery to get the first result (or Single if there should be only one)
BOOK entity = db.BOOKS
.Where(s => s.ID == (from p in db.LIBRARY
from b in db.BOOKS
where (p.ID == 123) && (p.idpage == b.idpage)
select b.fields).First());
You should be able to use the navigation properties on your BOOKS class to do something like this:
var bookIds = db.BOOKS.Where(b => b.LIBRARIES.Any(l => l.ID == 123))
.Select(b => b.ID)
This query takes a group of comments, then counts their upvotes and downvotes in the tblCommentVotes table.
At the moment, it counts these via the select new statement, in the form of a subquery. Would this be more efficient if it was in some sort of group by in the main query? Also if it would, could anyone show me how to do this, as I can't work out how you would do this.
// Get comments
var q = (
from C in db.tblComments
where
C.CategoryID == Category &&
C.IdentifierID == Identifier
join A in db.tblForumAuthors on C.UserID equals A.Author_ID
orderby C.PostDate descending
select new
{
C,
A.Username,
UpVotes = (from V in db.tblCommentVotes where V.CommentID == C.ID && V.UpVote == true select new { V.ID }).Count(),
DownVotes = (from V in db.tblCommentVotes where V.CommentID == C.ID && V.UpVote == false select new { V.ID }).Count()
}
)
.Skip(ToSkip > 0 ? ToSkip : 0)
.Take(ToTake > 0 ? ToTake : int.MaxValue);
What you need to do is to do an left outer join of the db.tblCommentVotes in the query expression, cause probably there might be no commentVotes?
When you have that, you should be able to perform ONE query in order to get your result.
It might look like this:
var q = (
from C in db.tblComments
where
C.CategoryID == Category &&
C.IdentifierID == Identifier
join A in db.tblForumAuthors on C.UserID equals A.Author_ID
// the following two lines are the left outer join thing.
join voteTemp in db.tblCommentVotes on voteTemp.CommentID equals C.ID into voteJoin
from vote in voteJoin.DefaultIfEmpty()
orderby C.PostDate descending
group C by new { Comment = C, Username = A.Username } into g
select new
{
g.Key.Comment,
g.Key.Username,
UpVotes = g.Count(x => x.UpVote),
DownVotes = g.Count(x => !x.UpVote)
}
)
.Skip(ToSkip > 0 ? ToSkip : 0)
.Take(ToTake > 0 ? ToTake : int.MaxValue);
This is untested and might not even compile, but I think it should be something like this.
db.tblComments.Where(c => c.CategoryID == Category && c.IdentifierID == Identifier)
.Join(db.tblForumAuthors, c => c.UserID, a => a.Author_ID,
(c, a) =>
new
{
CommentID = c,
AuthorName = a.UserName,
UpVotes = c.Join(db.tblCommentVotes, c => c.CommentID
v => v.CommentID,
(c, v) => v).Count(v => v.UpVote)
DownVotes = c.Join(db.tblCommentVotes, c => c.CommentID
v => v.CommentID,
(c, v) => v).Count(v => v.DownVote)
});
To optimise it's best first to measure.
Try, using something like LinqPad to view the generated SQL
Then use SQL Server Management Studio to see the query plan for that SQL
or:
Try running the code and seeing what SQL trace tells you is happening
Without the DB, it's quite hard (but fun) to guess whether that Linq will result in a single query or in multiple queries for working out the UpVotes and DownVotes. My guess is that calculating the UpVotes and DownVotes this way could be quite expensive - it may result in 2 additional queries per comment.
http://www.thereforesystems.com/view-query-generate-by-linq-to-sql/
without analyzing whats being output this question is impossible to answer.. however the link provided above should give you the tools necessary to perform this analysis yourself.