Subselect with LINQ - linq

I want to do a subselect with LINQ
What I have, but incorrect
var diretores = from item in db.San_PropostaConversa
join sc in db.San_Credenciada
on (item.Credenciada_Id) equals sc.Credenciada_Id
join sp in db.San_Proposta
on (item.Proposta_Id) equals sp.Proposta_Id
join si in db.San_Imovel
on (sp.Imovel_Id) equals si.Imovel_Id
join su in db.San_Usuario
on (item.Usuario_Id) equals su.Usuario_Id
where item.Proposta_Id == proposta
orderby item.DataHora descending
select new
{
sc.Apelido,
su.NomeCompleto,
su.DescricaoCargo1,
item.Comentario,
item.DataHora,
sp.Imovel_Id,
CredenciadaCaptadora_Id = si.Credenciada_Id,
item.Credenciada_Id,
(from item2 in db.San_Usuario
where item2.Cargo_Id == 9
&& item2.Excluido == 0
&& item2.Credenciada_Id == item.Credenciada_Id
select item2.Email)
};
In my SELECT statement, I want to recover an email column following some conditions that are specified in my WHERE clause.
Error
Invalid anonymous type member declarator. Anonymous type members must
be declared with a member assignment, simple name or member access

You have 2 problems in your linq expression:
You need to assign the result of the subquery to a member of the new anonymous type.
I think you only want to select 1 email with your subquery, so you need to use Single()/SingleOrDefault() or First()/FirstOrDefault().
Try this:
var diretores = from item in db.San_PropostaConversa
join sc in db.San_Credenciada
on item.Credenciada_Id equals sc.Credenciada_Id
join sp in db.San_Proposta
on (item.Proposta_Id) equals sp.Proposta_Id
join si in db.San_Imovel
on sp.Imovel_Id equals si.Imovel_Id
join su in db.San_Usuario
on item.Usuario_Id equals su.Usuario_Id
where item.Proposta_Id == proposta
orderby item.DataHora descending
select new
{
Apelido = sc.Apelido,
NomeCompleto = su.NomeCompleto,
DescricaoCargo1 = su.DescricaoCargo1,
Comentario = item.Comentario,
DataHora = item.DataHora,
Imovel_Id = sp.Imovel_Id,
CredenciadaCaptadora_Id = si.Credenciada_Id,
Credenciada_Id = item.Credenciada_Id,
Email = (from item2 in db.San_Usuario
where item2.Cargo_Id == 9
&& item2.Excluido == 0
&& item2.Credenciada_Id == item.Credenciada_Id
select item2.Email).FirstOrDefault()
};

Mostly this error occurring for unavailable assigning variable,
please try this
it will help you
var diretores = from item in db.San_PropostaConversa
join sc in db.San_Credenciada
on (item.Credenciada_Id) equals sc.Credenciada_Id
join sp in db.San_Proposta
on (item.Proposta_Id) equals sp.Proposta_Id
join si in db.San_Imovel
on (sp.Imovel_Id) equals si.Imovel_Id
join su in db.San_Usuario
on (item.Usuario_Id) equals su.Usuario_Id
where item.Proposta_Id == proposta
orderby item.DataHora descending
select new
{
Apelido=sc.Apelido,
NomeCompleto=su.NomeCompleto,
DescricaoCargo1=su.DescricaoCargo1,
Comentario=item.Comentario,
DataHora=item.DataHora,
Imovel_Id=sp.Imovel_Id,
CredenciadaCaptadora_Id = si.Credenciada_Id,
Credenciada_Id= item.Credenciada_Id,
result= (from item2 in db.San_Usuario
where item2.Cargo_Id == 9
&& item2.Excluido == 0
&& item2.Credenciada_Id == item.Credenciada_Id
select item2.Email)
};

Related

Linq query - ON clause of inner join cannot compare two Guids

If the person you are searching is a CIA emplyee, take his CIAJobs.EmployerID, otherwise select People.ID
SELECT
case when CIAJobs.EmployeeID IS NULL then People.ID
else CIAJobs.EmployerID
end
FROM [FMO].[People] AS p
LEFT JOIN [FMO].[CIAJobs] j
ON (p.ID = j.[EmployeeID])
AND (j.[relationshipType] = '25a8d79d-377e-4108-8c92-0ef9a2e1ab63')
where p.ID = '1b66e032-94b2-e811-96e0-f48c508e38a2' // id of person you search for
OR
j.[EmployeeID] = '1b66e032-94b2-e811-96e0-f48c508e38a2' // id of person you search for
I tried doing this in Linq:
var a = from l in People
join x in CIAJobs
on l.Id equals x.EmployeeID && x.RelationshipTypeGuid equals Guid.Parse('25a8d79d-377e-4108-8c92-0ef9a2e1ab63')
into gcomplex
from xx in gcomplex.DefaultIfEmpty()
select (xx.EmployeeID == null) ? l.EmployeeId : x.EmployerID;
var b = a.ToList();
why does the query show an error because of this chunk: && x.RelationshipTypeGuid equals Guid.Parse('25a8d79d-377e-4108-8c92-0ef9a2e1ab63')
If I remove this part it shows no error.
Error is: operator && cannot be applied to operands of type Guid and Guid.
Can you help me correct the Linq query please logically and syntactically? Thank you.
You don't need join for multiple conditions in this scenario. Use this
var a = from l in People
join x in CIAJobs
.Where(z=>z.RelationshipTypeGuid
.Equals(Guid.Parse('25a8d79d-377e-4108-8c92-0ef9a2e1ab63')))
on l.Id equals x.EmployeeID
into gcomplex
from xx in gcomplex.DefaultIfEmpty()
select (xx.EmployeeID == null) ? l.EmployeeId : x.EmployerID;
var b = a.ToList();
But based on your problem statement this should do
var a = from l in People
join x in CIAJobs
on l.Id equals x.EmployeeID
into gcomplex
from xx in gcomplex.DefaultIfEmpty()
select (xx == null) ? l.EmployeeId : xx.EmployerID;
var b = a.ToList();

LINQ Multiple table left join, distinct count not giving proper result

I am sql query us producing correct result, but when i'm doing the same in LINQ. Output is incorrect. Please let me know where my making mistake.
Following linq query that i created.
LINQ Query:
List<UserModel> Model = (from users in db.UserM
join ct in db.CustT on users.UserId equals ct.UserID into group1
from g1 in group1.DefaultIfEmpty()
join ti in db.TestIn on g1.TestId equals ti.TestID into group2
from g2 in group2.DefaultIfEmpty()
where (users.CustomerId==CustomerId) && (users.RoleId == 4) && (users.Status == 1)
group new
{
g2.TestInvitationID,
g2.TestID,
}
by new
{
users.FirstName,
users.CreatedOn,
users.Email,
users.UserId
} into group4
select new UserModel
{
Name = group4.Key.FirstName,
CreatedOn = group4.Key.CreatedOn,
EmailId = group4.Key.Email,
UserId = group4.Key.UserId,
NoOfTestTaken = group4.Select(x=>x.TestID).Distinct().Count(),
NoOfInvitationsSent = group4.Count(x => x.TestInvitationID != 0)
}).ToList();
SQL Query:
SELECT IsNull(COUNT(distinct TS.TestId),0) AS NoOfTests,
IsNull(COUNT(TS.TestInvitationID),0) AS NoOfInvitations,
UM.Email,
UM.UserId,
UM.FirstName,
UM.CreatedOn
FROM UserM as UM
left JOIN CustT AS CT
ON UM.UserId=CT.UserId
left JOIN TestIn AS TS
ON TS.TestId = CT.TestId
WHERE UM.CustomerId=41
AND UM.RoleId=4
and UM.[Status]=1
GROUP BY UM.UserId, UM.Email, UM.FirstName, UM.CreatedOn
Tables:
"UserM" - columns: UserId, Email, FirstName, CreatedOn
"CustT" - columns: TestId, UserId,
"TestIn" - columns: TestInvitationId, TestId
The difference between SQL COUNT(expr) and LINQ Count is that the former excludes NULL values, which produces a difference when used on right side of a left outer join with no matching records (SQL will produce 0 while LINQ 1). The closest LINQ equivalent is Count(expr != null).
So the direct translation of your SQL query would be like this (note that the generated SQL query could and most likely will be different):
(A side note: When converting SQL query to LINQ, it's good to use the same aliases to make it easier to see the mappings)
var query =
from um in db.UserMasters
join ct in db.CustTests on um.UserId equals ct.UserID
into ctGroup from ct in ctGroup.DefaultIfEmpty() // left outer join
join ts in db.TestInvitaions on ct.TestId equals ts.TestID
into tsGroup from ts in tsGroup.DefaultIfEmpty() // left outer join
where um.CustomerId == UserSession.CustomerId
&& um.RoleId == 4
&& um.Status == 1
group ts by new { um.UserId, um.Email, um.FirstName, um.CreatedOn } into g
select new UserModel
{
Name = g.Key.FirstName,
CreatedOn = g.Key.CreatedOn,
EmailId = g.Key.Email,
UserId = g.Key.UserId,
NoOfTestTaken = g.Where(ts => ts != null).Select(ts => ts.TestID).Distinct().Count(),
NoOfInvitationsSent = g.Count(ts => ts != null)
};
var result = query.ToList();
I suspect that the following row is the problem because is not the same like in your sql:
Linq:
NoOfInvitationsSent = group4.Count(x => x.TestInvitationID != 0)
SQL:
IsNull(COUNT(TS.TestInvitationID),0) AS NoOfInvitations
Due to counting items from a left join Linq should be instead:
NoOfInvitationsSent = group4.Where(i => i != null).Count()
To put it all together, with a bit of better formatting:
var model = (from users in db.UserMasters
join ct in db.CustTests on users.UserId equals ct.UserID into group1
from ct in group1.DefaultIfEmpty()
join ti in db.TestInvitaions on ct.TestId equals ti.TestID into group2
from ct in group2.DefaultIfEmpty()
where users.CustomerId == UserSession.CustomerId &&
users.RoleId == 4 &&
users.Status == 1
group new { ct.TestInvitationID, ct.TestID }
by new
{
users.FirstName,
users.CreatedOn,
users.Email,
users.UserId
} into grouping
select new UserModel
{
Name = grouping.Key.FirstName,
CreatedOn = grouping.Key.CreatedOn,
EmailId = grouping.Key.Email,
UserId = grouping.Key.UserId,
NoOfTestTaken = grouping.Where(i => i != null).Select(x => x.TestID).Distinct().Count(),
NoOfInvitationsSent = grouping.Where(i => i != null).Count()
}).ToList();

Linq - Subquery count

Problem: Am trying to rewrite this in Linq:
listOfUsersForReviewer is an IEnumerable<User>
int countOfGreenUsers = 0;
foreach (var user in listOfUsersForReviewer)
{
var u = (from reviewitems in context.ReviewItems
join groupaccountlinks in context.GroupAccountLinks on reviewitems.GroupAccountID equals groupaccountlinks.GroupAccountID
join reviews in context.Reviews on reviewitems.ReviewID equals reviews.ReviewID
join applications in context.Applications on reviews.ApplicationID equals applications.ApplicationID
join reviewers in context.Reviewers on applications.ResponsibleReviewerID equals reviewers.ReviewerID
join accounts in context.Accounts on groupaccountlinks.AccountID equals accounts.AccountID
join users in context.RBSUsers on accounts.UserID equals users.UserID
where
users.UserID == user.UserID &&
reviewers.FullyQualifiedLogin == fullyQualifiedLogin &&
reviews.ReviewStatusID == (byte)Enums.ReviewStatus.InProgress &&
reviewitems.ReviewItemStatusID == (byte)Enums.ReviewItemStatus.Unapproved
select reviewitems);
byte colour = (byte)Enums.UserStatusColour.Red;
if (u.Count() == 0)
{
colour = (byte)Enums.UserStatusColour.Green;
countOfGreenUsers++;
}
}
have tried to create an anonymous type, however this doesn't compile.
// select number of green users
var x = from user in listOfUsersForReviewer
from reviewitems in context.ReviewItems
join groupaccountlinks in context.GroupAccountLinks on reviewitems.GroupAccountID equals
groupaccountlinks.GroupAccountID
join reviews in context.Reviews on reviewitems.ReviewID equals reviews.ReviewID
join applications in context.Applications on reviews.ApplicationID equals applications.ApplicationID
join reviewers in context.Reviewers on applications.ResponsibleReviewerID equals
reviewers.ReviewerID
join accounts in context.Accounts on groupaccountlinks.AccountID equals accounts.AccountID
join users in context.RBSUsers on accounts.UserID equals users.UserID
where
users.UserID == user.UserID &&
reviewers.FullyQualifiedLogin == fullyQualifiedLogin &&
reviews.ReviewStatusID == (byte)Enums.ReviewStatus.InProgress &&
reviewitems.ReviewItemStatusID == (byte)Enums.ReviewItemStatus.Unapproved
select new
{
UserID = user.UserID,
CountOfGreen = reviewitems.Count()
};
Add grouping clause
var x = from user in listOfUsersForReviewer
from reviewitems in context.ReviewItems
join groupaccountlinks in context.GroupAccountLinks on reviewitems.GroupAccountID equals
groupaccountlinks.GroupAccountID
join reviews in context.Reviews on reviewitems.ReviewID equals reviews.ReviewID
join applications in context.Applications on reviews.ApplicationID equals applications.ApplicationID
join reviewers in context.Reviewers on applications.ResponsibleReviewerID equals
reviewers.ReviewerID
join accounts in context.Accounts on groupaccountlinks.AccountID equals accounts.AccountID
join users in context.RBSUsers on accounts.UserID equals users.UserID
where
users.UserID == user.UserID &&
reviewers.FullyQualifiedLogin == fullyQualifiedLogin &&
reviews.ReviewStatusID == (byte)Enums.ReviewStatus.InProgress &&
reviewitems.ReviewItemStatusID == (byte)Enums.ReviewItemStatus.Unapproved
group user by user.UserID into grouping
select new
{
UserID = grouping.Key,
CountOfGreen = grouping.Count()
};
I ended up rethinking me logic and split this query into 2 simpler ones.
Tools I used were: SQL Server Management Studio (graphical representation), Linqer and potentially Linqpad
And writing the query in English helped a lot.

Combining two tables using linq

i have two linq - sql queries, and im wondering how to join them..
First Query
var ab = from a in Items_worker.getCEAItems()
where a.ProjectCode == lbl_projectCode.Text
select new
{
a.ID
};
Second Query
var j = from c in tblInc_worker.get(c => c.MarginID == MarginID && c.IncTypeID == "CAPEX")
orderby c.DateCreated
select c.ID;
First Query would return:
fasf-1212-1212-1212-1212
afaa-1414-1414-1414-1414
Second Query would return:
fasf-1212-1212-1212-1212
afaa-1414-1414-1414-1414
0000-0000-0000-0000-0000
1111-1111-1111-1111-1111
question is how can i possibly join the two table. Wherein the second query should return all of the records with the same ID found in the first query plus the id containing "0000-0000-0000-0000-0000" second query..
The result should be:
fasf-1212-1212-1212-1212
afaa-1414-1414-1414-1414
0000-0000-0000-0000-0000
You can use union to join the both queries, for example split your second query in two with conditions like :
var ab = from a in Items_worker.getCEAItems()
where a.ProjectCode == lbl_projectCode.Text
select new
{
a.ID
};
var j = from c in tblInc_worker.get(c => c.MarginID == MarginID && c.IncTypeID == "CAPEX")
orderby c.DateCreated
select c.ID where c.ID.Equals("0000-0000-0000-0000-0000");
var j1 = from c in tblInc_worker.get(c => c.MarginID == MarginID && c.IncTypeID == "CAPEX")
orderby c.DateCreated
select c.ID where !(c.ID.Equals("0000-0000-0000-0000-0000"));
var result = ab.Union(j.Union(j1));
Hope this helps..

Use of where in multiple joins to remove rows - linq

I have a table of orders. the status is on the soilorders which is joined to the orders.
I only want to return orders where the joined soilorder does not have status "Removed".
I had thought that
join sso in db.SoilSamplingOrders on ord.order_id equals sso.order_id
where sso.status.Equals("Removed")!=true
but then no records are returned!
thanks for any help (query below)
var query =
from ord in db.Orders
join sso in db.SoilSamplingOrders on ord.order_id equals sso.order_id
where sso.status.Equals("Removed")!=true
join cust in db.Customers on ord.customer_id equals cust.customer_id
select new Listing
{
assigned_to = sso.assigned_to,
company = cust.company,
order_id = ord.order_id,
order_created = ord.order_created,
customer_id = ord.customer_id,
order_created_by_employ_id = ord.order_created_by_employ_id,
first_farm_on_order = (from f in db.SoilSamplingSubJobs
where f.order_id == ord.order_id
select new ListingSubJob { first_farm_on_order = f.farm }).
AsEnumerable().First().first_farm_on_order,
total_fields = (from f in db.SoilSamplingSubJobs
where f.order_id == ord.order_id
select new { f.sssj_id }).AsEnumerable().Count(),
total_area = (float?) (from f in db.SoilSamplingSubJobs
where f.order_id == ord.order_id && f.area_ha != null
select f.area_ha ).Sum() ?? 0 ,
total_area_ph_density = (float?)(from f in db.SoilSamplingSubJobs
where f.order_id == ord.order_id && f.ph != null
select f.ph).Sum() ?? 0,
};
DOH! Just as nature abhors a vacuum, anything Null cannot be included in the select. Added values to the status field and bom it works.

Resources