SubSonic3 linq problem - linq

I have this query:
var rights = from gu in db.GroupUsers
join g in db.Groups on gu.GroupId equals g.GroupId
join gr in db.GroupRights on g.GroupId equals gr.GroupId
join r in db.Rights on gr.RightId equals r.RightId
where gu.UserId == userId && g.IsDeleted == false
select r;
It gets translated to:
SELECT [t0].[Name] AS Name1, [t0].[RightId] AS RightId1
FROM [dbo].[GroupUsers] AS t1
INNER JOIN [dbo].[Groups] AS t2
ON ([t1].[GroupId] = [t2].[GroupId])
INNER JOIN [dbo].[GroupRights] AS t3
ON ([t2].[GroupId] = [t3].[GroupId])
INNER JOIN [dbo].[Rights] AS t0
ON ([t3].[RightId] = [t0].[RightId])
WHERE (([t1].[UserId] = 3345) AND ([t2].[IsDeleted] = 0))
This is still ok, but in .NET my SubSonic objects are all empty. So the query returns 15 objects, but Name and RightId are an empty string and -1.
Can this have anything to do with the fact that Name is returned as Name1 and RightId is returned as RightId1?
I'll have a look into the source code of SubSonic3 to find something.
SubSonic3 Source Code: the query does get translated to the sql above. Because of the Name1 and RightId1, the Load in Database.cs doesn't work properly. The line :
currentProp = cachedProps.SingleOrDefault
(x => x.Name.Equals(pName, StringComparison.InvariantCultureIgnoreCase));
doesn't find the currentProp because the currentProp is Name (and RightId) and not Name1 and RightId1. Well, fixing this won't be for today. Maybe someone from SubSonic3 can have a look at this, because it's pretty annoying. I could write a sort of hack into the source code, but it won't be pretty. I guess the translation should be cleaned up so that Name1 and RightId1 are translated back to Name and RightId.
In TSqlFormatter.cs there's next line that adds these AS strings
(in method :
protected override Expression VisitSelect(SelectExpression select)
{
...
if (!string.IsNullOrEmpty(column.Name) && (c == null || c.Name != column.Name))
{
sb.Append(" AS ");
sb.Append(column.Name);
}
...
}
If I put the two Appends in comment, then my linq query does work and I do get the right data. But I guess those two lines are there for a reason, but what reason? In which usecase are the two lines necessary?

Related

How to solve this Error in Linq : Operator '!=' cannot be applied to operands of type 'int' and 'System.Linq.IQueryable<int>'

var ll = from a in db.EmployeeMasters
where a.EmployeeID != (from d in db.EmployeeMasters
join c in db.PerformanceDetails on d.EmployeeID equals c.EmployeeID
join z in db.ProjectMasters on c.ProjectID equals z.ProjectID
into ss
from z in ss.DefaultIfEmpty()
where z.ProjectName == name || z.ProjectName == name1
select d.EmployeeID)
select a.EmployeeName;
It returns an error messages like below
Operator '!=' cannot be applied to operands of type 'int' and 'System.Linq.IQueryable'
I want to add this Linq query in http post method to view output in postman
Anyone Please help me to solve this
Actual question is select employees who are not part of 2 projects like (CRM, Automation)
Part of both project employees are in another project but some of the employees not in any projects
My Entity Framework Data Model is shown here:
name and name1 are given parameters for project names
You're making this much harder than necessary. In the first place, you should use these navigation properties EF kindly creates for you, instead of using verbose and error-prone join statements. Doing that, it's much easier to write a greatly simplified predicate:
var ll = from a in db.EmployeeMasters
where !a.PerformanceDetails
.Any(pd => pd.ProjectMaster.ProjectName == name
|| pd.ProjectMaster.ProjectName == name1)
select a.EmployeeName;
This is a different query --it translates into EXISTS-- but the result is the same and the query plan may even be better. Also, it's much easier to add more predicates to it later, if necessary.
Your question isn't really clear, but the error is pretty clear, you cannot compare type int and System.Linq.IQueryable<int>.
I assume your want something like this :
var ll = from a in db.EmployeeMasters
where !(from d in db.EmployeeMasters
join c in db.PerformanceDetails on d.EmployeeID equals c.EmployeeID
join z in db.ProjectMasters on c.ProjectID equals z.ProjectID
into ss
from z in ss.DefaultIfEmpty()
where z.ProjectName == name || z.ProjectName == name1
select d.EmployeeID).Contains(a.EmployeeID)
select a.EmployeeName;
Here we're looking for EmployeeIDs that do not appear in your query result.
int[] EmployeeIDs = (from em in db.EmployeeMasters
join pd in db.PerformanceDetails on em.EmployeeID equals pd.EmployeeID into pdRes
from pdResult in pdRes.DefaultIfEmpty()
join pm in db.ProjectMasters on pdResult.ProjectID equals pm.ProjectID into pmRes
from pmResult in pmRes.DefaultIfEmpty()
where (pmResult.ProjectName == "Automation" || pmResult.ProjectName == "CRM Customer")
select em.EmployeeID
).Distinct().ToArray();
var empResult = (from em in db.EmployeeMasters
where !EmployeeIDs.Contains(em.EmployeeID)
select new
{
EmployeeName = em.EmployeeName
}).ToList();

What is the difference between these two linq queries? The first one will not work. The second will. Why?

I have my code using the following linq:
var consulta = from grupo in Contexto.Set<GRUPOCONTRATO>()
join detalhe in Contexto.Set<GRUPOCONTRATODETALHE>()
on grupo.CDGRUPOCONTRATO equals detalhe.CDGRUPOCONTRATO
where grupo.NOGRUPOCONTRATO.Contains("FACIL")
&& detalhe.NRCONTRATO == carteira.NumeroDoContrato
select detalhe;
PlanoFacil = consulta.Any();
The code above wont work and throws an exception like this:
Object of type 'System.Data.Objects.ObjectQuery1[Dominio.PERICIA]' cannot be converted to type 'System.Data.Entity.IDbSet1[Dominio.PERICIA]'.
Please note that it points to a problem with another entity (PERICIA) which has nothing to do with the query and has no relationship with the two entities in the query...
But if I split the query like this it works:
var consulta = from grupo in Contexto.Set<GRUPOCONTRATO>()
join detalhe in Contexto.Set<GRUPOCONTRATODETALHE>()
on grupo.CDGRUPOCONTRATO equals detalhe.CDGRUPOCONTRATO
where grupo.NOGRUPOCONTRATO.Contains("FACIL")
//&& detalhe.NRCONTRATO == carteira.NumeroDoContrato
select detalhe;
PlanoFacil = consulta.Any(detalhe => detalhe.NRCONTRATO == carteira.NumeroDoContrato);
Why?

How to do a simple Count in Linq?

I wanted to do a paging style table, but NeerDinner example fetches the entire data into a PaggingList type, and I have more than 10 000 rows to be fetched, so I skipped that part.
so I come up with this query
var r = (from p in db.Prizes
join c in db.Calendars on p.calendar_id equals c.calendar_id
join ch in db.Challenges on c.calendar_id equals ch.calendar_id
join ca in db.ChallengeAnswers on ch.challenge_id equals ca.challenge_id
join cr in db.ChallengeResponses on ca.challenge_answer_id equals cr.challenge_answer_id
where
p.prize_id.Equals(prizeId)
&& ch.day >= p.from_day && ch.day <= p.to_day
&& ca.correct.Equals(true)
&& ch.day.Equals(day)
orderby cr.Subscribers.name
select new PossibleWinner()
{
Name = cr.Subscribers.name,
Email = cr.Subscribers.email,
SubscriberId = cr.subscriber_id,
ChallengeDay = ch.day,
Question = ch.question,
Answer = ca.answer
})
.Skip(size * page)
.Take(size);
Problem is, how can I get the total number of results before the Take part?
I was thinking of:
var t = (from p in db.JK_Prizes
join c in db.JK_Calendars on p.calendar_id equals c.calendar_id
join ch in db.JK_Challenges on c.calendar_id equals ch.calendar_id
join ca in db.JK_ChallengeAnswers on ch.challenge_id equals ca.challenge_id
join cr in db.JK_ChallengeResponses on ca.challenge_answer_id equals cr.challenge_answer_id
where
p.prize_id.Equals(prizeId)
&& ch.day >= p.from_day && ch.day <= p.to_day
&& ca.correct.Equals(true)
&& ch.day.Equals(day)
select cr.subscriber_id)
.Count();
but that will do the query all over again...
anyone has suggestions on how can I do this effectively ?
If you take a query as such:
var qry = (from x in y
select x).Count();
...LINQ to SQL will be clever enough to make this a SELECT COUNT query, which is potentially rather efficient (efficiency will depend more on the conditions in the query). Bottom line is that the count operation happens in the database, not in LINQ code.
Writing my old comments :Well i was facing the same issue some time back and then i came up with LINQ to SP =). Make an SP and drop that into your entities and use it.you can get write Sp according to your need like pulling total record column too. It is more easy and fast as compare to that whet you are using wright now.
You can put count for query logic as well as, see the sample as below:
public int GetTotalCountForAllEmployeesByReportsTo(int? reportsTo, string orderBy = default(string), int startRowIndex = default(int), int maximumRows = default(int))
{
//Validate Input
if (reportsTo.IsEmpty())
return GetTotalCountForAllEmployees(orderBy, startRowIndex, maximumRows);
return _DatabaseContext.Employees.Count(employee => reportsTo == null ? employee.ReportsTo == null : employee.ReportsTo == reportsTo);
}

Greater Than Condition in Linq Join

I had tried to join two table conditionally but it is giving me syntax error. I tried to find solution in the net but i cannot find how to do conditional join with condition. The only other alternative is to get the value first from one table and make a query again.
I just want to confirm if there is any other way to do conditional join with linq.
Here is my code, I am trying to find all position that is equal or lower than me. Basically I want to get my peers and subordinates.
from e in entity.M_Employee
join p in entity.M_Position on e.PostionId >= p.PositionId
select p;
You can't do that with a LINQ joins - LINQ only supports equijoins. However, you can do this:
var query = from e in entity.M_Employee
from p in entity.M_Position
where e.PostionId >= p.PositionId
select p;
Or a slightly alternative but equivalent approach:
var query = entity.M_Employee
.SelectMany(e => entity.M_Position
.Where(p => e.PostionId >= p.PositionId));
Following:
from e in entity.M_Employee
from p in entity.M_Position.Where(p => e.PostionId >= p.PositionId)
select p;
will produce exactly the same SQL you are after (INNER JOIN Position P ON E..PostionId >= P.PositionId).
var currentDetails = from c in customers
group c by new { c.Name, c.Authed } into g
where g.Key.Authed == "True"
select g.OrderByDescending(t => t.EffectiveDate).First();
var currentAndUnauthorised = (from c in customers
join cd in currentDetails
on c.Name equals cd.Name
where c.EffectiveDate >= cd.EffectiveDate
select c).OrderBy(o => o.CoverId).ThenBy(o => o.EffectiveDate);
If you have a table of historic detail changes including authorisation status and effective date. The first query finds each customers current details and the second query adds all subsequent unauthorised detail changes in the table.
Hope this is helpful as it took me some time and help to get too.

Stuck on a subquery that is grouping, in Linq`

I have some Linq code and it's working fine. It's a query that has a subquery in the Where clause. This subquery is doing a groupby. Works great.
The problem is that I don't know how to grab one of the results from the subquery out of the subquery into the parent.
Frst, here's the code. After that, I'll expplain what piece of data i'm wanting to extract.
var results = (from a in db.tblProducts
where (from r in db.tblReviews
where r.IdUserModified == 1
group r by
new
{
r.tblAddress.IdProductCode_Alpha,
r.tblAddress.IdProductCode_Beta,
r.tblAddress.IdProductCode_Gamma
}
into productGroup
orderby productGroup.Count() descending
select
new
{
productGroup.Key.IdProductCode_Alpha,
productGroup.Key.IdProductCode_Beta,
productGroup.Key.IdProductCode_Gamma,
ReviewCount = productGroup.Count()
}).Take(3)
.Any(
r =>
r.IdProductCode_Alpha== a.IdProductCode_Alpha&&
r.IdProductCode_Beta== a.IdProductCode_Beta&&
r.IdProductCode_Gamma== a.IdProductCode_Gamma)
where a.ProductFirstName == ""
select new {a.IdProduct, a.FullName}).ToList();
Ok. I've changed some field and tables names to protect the innocent. :)
See this last line :-
select new {a.IdProduct, a.FullName}).ToList();
I wish to include in that the ReviewCount (from the subquery). I'm jus not sure how.
To help understand the problem, this is what the data looks like.
Sub Query
IdProductCode_Alpha = 1, IdProductCode_Beta = 2, IdProductCode_Gamma = 3, ReviewCount = 10
... row 2 ...
... row 3 ...
Parent Query
IdProduct = 69, FullName = 'Jon Skeet's Wonder Balm'
So the subquery grabs the actual data i need. The parent query determines the correct product, based on the subquery filters.
EDIT 1: Schema
tblProducts
IdProductCode
FullName
ProductFirstName
tblReviews (each product has zero to many reviews)
IdProduct
IdProductCode_Alpha (can be null)
IdProductCode_Beta (can be null)
IdProductCode_Gamma (can be null)
IdPerson
So i'm trying to find the top 3 products a person has done reviews on.
The linq works perfectly... except i just don't know how to include the COUNT in the parent query (ie. pull that result from the subquery).
Cheers :)
Got it myself. Take note of the double from at the start of the query, then the Any() being replaced by a Where() clause.
var results = (from a in db.tblProducts
from g in (
from r in db.tblReviews
where r.IdUserModified == 1
group r by
new
{
r.tblAddress.IdProductCode_Alpha,
r.tblAddress.IdProductCode_Beta,
r.tblAddress.IdProductCode_Gamma
}
into productGroup
orderby productGroup.Count() descending
select
new
{
productGroup.Key.IdProductCode_Alpha,
productGroup.Key.IdProductCode_Beta,
productGroup.Key.IdProductCode_Gamma,
ReviewCount = productGroup.Count()
})
.Take(3)
Where(g.IdProductCode_Alpha== a.IdProductCode_Alpha&&
g.IdProductCode_Beta== a.IdProductCode_Beta&&
g.IdProductCode_Gamma== a.IdProductCode_Gamma)
where a.ProductFirstName == ""
select new {a.IdProduct, a.FullName, g.ReviewCount}).ToList();
While I don't understand LINQ completely, but wouldn't the JOIN work?
I know my answer doesn't help but it looks like you need a JOIN with the inner table(?).
I agree with shahkalpesh, both about the schema and the join.
You should be able to refactor...
r => r.IdProductCode_Alpha == a.IdProductCode_Alpha &&
r.IdProductCode_Beta == a.IdProductCode_Beta &&
r.IdProductCode_Gamma == a.IdProductCode_Gamma
into an inner join with tblProducts.

Resources