Compare a linq value (int) to an int List using where clause - linq

I have a linq query which joins a couple of tables and returns the value into an object. The query was working fine, till i added a where clause to in. Aftre the where clause, my query returns null.
Here's the code:
List<Int32> resourceSupervisorIdList = new List<Int32>();
resourceSupervisorIdList.Add(searchCriteriaTimesheet.ResourceId);
foreach (resource res in allSubordinateResources)
{
if (!resourceSupervisorIdList.Contains(res.id_resource))
resourceSupervisorIdList.Add(res.id_resource);
}
using (tapEntities te = new tapEntities())
{
var timesheetAll = (from tsh in te.timesheet_header
join rs in te.resources on tsh.id_resource equals rs.id_resource
join tsd in te.timesheet_detail on tsh.id_timesheet equals tsd.id_timesheet
where (resourceSupervisorIdList.Contains(rs.id_resource_supervisor))
select new TimesheetHeaderDetailsItem()
{
OrganizationId = rs.id_organization,
ProjectId = tsd.id_project,
StartDate = tsh.dte_period_start,
EndDate = tsh.dte_period_end,
ApprovedDate = tsh.dte_approved,
RejectedDate = tsh.dte_rejected,
SubmittedDate = tsh.dte_submitted,
});
if (timesheetAll == null || timesheetAll.Count() == 0)
{
return result;
}
}
Now, after adding the where clause, the code runs into the if condition. There are matching records in the table, but still i'm not able to get any records.
rs.id_resource_supervisor
is of type int in the mysql db.

Related

How to return FirstOrDefaultAsync EF Linq to entity List query

I have this Linq to entity query that returns a list of visitors with joins.
I want a similar query to return a single record without the query being a List collection, but changing it to a basic select with FirstOrDefaultAsync gets the error "A query body must end with a select clause or a group clause"
public async Task<List<VisitorDetail>> GetOneVisitor(int visitorId)
{
var query = await (from v in _context.Visitors
where v.Id == visitorId
join d in _context.Categories on v.VisitCategoryId equals d.Id
join c in _context.Counters on v.AssignedCounter equals c.Host into counterGroup
from cg in counterGroup.DefaultIfEmpty()
select new
{
FirstName = v.FirstName,
LastName = v.LastName,
CounterDescription = cg.Description,
VisitCategory = d.Description
}).ToListAsync();
List<VisitorDetail> visitors = new();
foreach (var p in query)
{
visitors.Add(new VisitorDetail
{
FirstName = p.FirstName,
LastName = p.LastName,
CounterDescription = p.CounterDescription,
CategoryDescription = p.VisitCategory
});
}
return visitors;
}
If you want to keep DRY with LINQ to Entities, return IQueryable for your common queries and invoke materialization only when it is needed.
Your method can be rewritten in the following way:
public IQueryable<VisitorDetail> GetVisitorDetails(int visitorId)
{
var query =
from v in _context.Visitors
where v.Id == visitorId
join d in _context.Categories on v.VisitCategoryId equals d.Id
join c in _context.Counters on v.AssignedCounter equals c.Host into counterGroup
from cg in counterGroup.DefaultIfEmpty()
select new VisitorDetail
{
FirstName = v.FirstName,
LastName = v.LastName,
CounterDescription = cg.Description,
CategoryDescription = d.Description
};
return query;
}
var many = await GetVisitorDetails(visitorId).ToListAsync();
var one = await GetVisitorDetails(visitorId).FirstOrDefaultAsync();

Querydsl - filter on Left join with subquery

I have one of the complex query dynamically generated through Querydsl predicate and JPQL. I am also using the Q classes.
I am able to generate the following query by passing a predicate to the JPA repository.
select company0_.id as id1_18_,
company0_.name as name2_18_
from company company0_
left outer join companyAddress companyadd1_ on company0_.id=companyadd1_.company_id
where company0_.id in
(select companyadd2_.company_id
from companyAddress companyadd2_
where companyadd2_.address_type='1')
order by companyadd1_.addressline1;
but I want the query mentioned below
select company0_.id as id1_18_,
company0_.name as name2_18_
from company company0_
left outer join companyAddress companyadd1_ on company0_.id=companyadd1_.company_id
and companyadd1_.status = 'Active' -- New added(Failed to implement this)
where company0_.id in
(select companyadd2_.company_id
from companyAddress companyadd2_
where companyadd2_.address_type='1'
and and companyadd2_.status = 'Active') -- New Added(I am able to achieve this)
order by companyadd1_.addressline1;
We are using following kind of code, I can not possibly to share exact code due to security concern but you can help me by providing basic structure or code to achieve this.
final JPQLQuery<QCompanyAlias> subQuery = new JPAQuery<>();
BooleanExpression exp = null;
QueryBase<?> q = (QueryBase<?>) subQuery.from(qCompanyAddress);
if (requestMap.containsKey(CompanyQueryConstants.ADDRESS_TYPE)) {
BooleanExpression addrExp = null;
for (String addressType : addressTypes) {
if (addrExp == null) {
addrExp = qCompanyAddress.addressType.addressTypeCode.eq(addressType);
} else {
addrExp = addrExp.or(qCompanyAddress.addressType.addressTypeCode.eq(addressType));
}
}
exp = addrExp;
}
To add join on two conditions use
new JPAQuery(em)
.from(qCompany)
.leftJoin(qCompany, qCompanyAddress.company)
.on(
qCompany.id.eq(qCompanyAddress.company.id)
.and(qCompanyAddress.status.eq(status))
);
For subquery try to use this
final JPQLQuery<QCompanyAlias> subQuery = new JPAQuery<>();
BooleanExpression exp = null;
QueryBase<?> q = (QueryBase<?>) subQuery.from(qCompanyAddress);
if (requestMap.containsKey(CompanyQueryConstants.ADDRESS_TYPE)) {
BooleanExpression addrExp = null;
for (String addressType : addressTypes) {
if (addrExp == null) {
addrExp = qCompanyAddress.addressType.addressTypeCode.eq(addressType);
} else {
addrExp = addrExp.or(qCompanyAddress.addressType.addressTypeCode.eq(addressType));
}
}
exp = addrExp;
}
BooleanExpression statusExp = qCompanyAddress.status.eq(status);
if(exp == null) {
exp = statusExp;
} else {
exp = statusExp.and(exp);
}
But in your case I can't understand the reason for filtering by status twice. Subquery filtering should be enought. I suspect that you can achieve the same result without subquery. It depends on your entities.

nullable object must have a value linq to sql query

I have the following linq query that is throwing an error if a budget doesn't have any categories. Am I doing something wrong? Can I just set sum to return 0 if there are no categories? I'm fairly new to linq to sql.
var r = from rec in DbContext.budgets
where rec.budgetID == updatedBudget.budgetID
select new
{
rec.budgetID,
rec.totalIncome,
totalSpent = rec.categories.Sum(a => a.amount)
};
return new JsonResult(r.FirstOrDefault(), JsonSettings);
you can try this.
var r = from rec in DbContext.budgets
where rec.budgetID == updatedBudget.budgetID
select new
{
rec.budgetID,
rec.totalIncome,
totalSpent = rec.categories != null ? rec.categories.Sum(a => a.amount) : 0
};
return new JsonResult(r.FirstOrDefault(), JsonSettings);

LINQ Update query with Join condition

trying to do LINQ Update query using join with on condition also And condition
Following my SQL Query
UPDATE tbl_gs_related_orders
SET RelatedCOI = sop.ServiceOrderNo
FROM tbl_service_order_progress sop
JOIN tbl_gs_related_orders ro ON sop.parentid = ro.RelatedOrderParentId
AND ro.RelatedCOIIdentifier collate database_default = sop.InstanceIdentifier collate database_default
WHERE ro.ParentId = #PARENTID
AND ro.relatedorderparentid IS NOT NULL
This Query i want to convert into LINQ SO following my update LINQ query but getting some error like "the type of one of the expressions in the join clause is incorrect type inference failed in the call to join"
var updateQuery = (from c in ctxParser.TBL_SERVICE_ORDER_PROGRESS
join o in ctxParser.tbl_GS_Related_Orders on new { ParentId = c.ParentId, InstanceIdentifier = c.InstanceIdentifier }
equals new { RelatedOrderParentId = o.RelatedOrderParentId, RelatedCOIIdentifier = o.RelatedCOIIdentifier }
where ro.RelatedOrderParentId == sParentId && ro.RelatedOrderParentId != null
select new
{
ServiceOrderNo = c.ServiceOrderNo,
Order = o
});
foreach (var item in updateQuery)
{
item.Order.RelatedCOI = item.ServiceOrderNo;
}
ctxParser.SaveChanges();
Use same aliases when creating Anonymous type for equals clause:
from c in ctxParser.TBL_SERVICE_ORDER_PROGRESS
join o in ctxParser.tbl_GS_Related_Orders on new { ParentId = c.ParentId, InstanceIdentifier = c.InstanceIdentifier }
equals new { ParentId = o.RelatedOrderParentId, InstanceIdentifier = o.RelatedCOIIdentifier }

LINQ - Joins in a dynamic query

Because of some business decisions I need to change a bit of what I was doing. Yay me. :)
Currently, I have:
public IOrderedQueryable<ProductDetail> GetProductList(string productGroupName, string productTypeName, Dictionary<string,List<string>> filterDictionary)
{
string whereClause = "ProductGroupName='" + productGroupName + "' AND ProductTypeName='" + productTypeName + "'";
string comma = "";
foreach (KeyValuePair<string, List<string>> myKVP in filterDictionary)
{
comma = "";
if (myKVP.Value.Count > 0)
{
whereClause = String.Format("{0} AND FieldName = {1} AND FieldValue IN (", whereClause, myKVP.Key);
foreach (string value in myKVP.Value)
{
whereClause = String.Format("{0}{1}'{2}'", whereClause, comma, value);
comma = ",";
}
whereClause = String.Format("{0})", whereClause);
}
}
var q = db.ProductDetail
.Where (whereClause)
.OrderBy ("ProductTypeName");
return q;
}
Instead of foing this directly, I now need to join through 2 other tables to apply the filter correctly. I'm trying to figure out how to correctly join in a dynamic LINQ query. In TSQL it would be something like:
SELECT pd.*
FROM ProductDetail pd
INNER JOIN ProductFilterAssignment pfa ON pd.ProductID = pfs.ProductID
INNER JOIN ProductFilter pf ON pfs.FIlterID = pf.FIlterID
WHERE pf.FieldName = 'var1' AND pf.FieldValue IN ('var1a','var1b','var1c',etc)
AND pf.FieldName = 'var2' AND pf.FieldValue IN ('var2a','var2b','var2c',etc)
Ouch. Yeah, that's a complicated requirement. You know, lambdas are cumulative, so you can do this much simpler if you use successive linq expressions. Note that subsequent linq expressions are using the prior expression result and the entire isn't actually executed until iterated.
public IOrderedQueryable<ProductDetail> GetProductList(string productGroupName, string productTypeName, Dictionary<string,List<string>> filterDictionary)
{
// Initial select on productGroupName and productTypeName
var products = from product in db.ProductDetail
where product.ProductGroupName == productGroupName && product.ProductTypeName == productTypeName
select product;
// Now add each filter item present.
foreach (KeyValuePair<string, List<string>> myKVP in filterDictionary)
{
products = from product in products
join pfa in db.ProductFilterAssignment on product.ProductID equals pfa.ProductID
join pf in db.Product on pfa.FilterID equals pf.FilterId
where pf.FieldName == myKVP.Key && myKVP.Value.Contains(pf.FieldValue)
select product;
}
return products.OrderBy ("ProductTypeName");
}
I don't have a good "answer" for you, but more of an aside. Check out LINQPad. You might even see an ad on the right-hand side of this page, too. It is very slick for writing LINQ queries. It might help in writing and validating this and any other future LINQ query you write.
Try to use Spolty Framework. It helps to do dynamic query for Linq To SQL and Entity Framework. You can dynamically create left/inner join, add conditions, orderings and other things. If you use Spolty Framework then your code will be look like below:
public IQueryable<ProductDetail> GetProductList(string productGroupName, string productTypeName, Dictionary<string, List<string>> filterDictionary)
{
// create root node
JoinNode productDetailNode = new JoinNode(typeof(ProductDetail));
productDetailNode.AddConditions(new Condition("ProductGroupName", productGroupName),
new Condition("ProductTypeName", productTypeName));
// if there are conditions than we create joins
if (filterDictionary.Count > 0)
{
// create joinNode
// INNER JOIN ProductFilterAssignment pfa ON pd.ProductID = pfs.ProductID
JoinNode productFilterAssignmentNode = new JoinNode(typeof(ProductFilterAssignment));
productDetailNode.AddChildren(productFilterAssignmentNode);
// create joinNode
// INNER JOIN ProductFilter pf ON pfs.FIlterID = pf.FIlterID
JoinNode productFilterNode = new JoinNode(typeof(ProductFilter));
productFilterNode.AddChildren(productFilterNode);
foreach (KeyValuePair<string, List<string>> myKVP in filterDictionary)
{
// create condition pf.FieldName = {1} And AND pf.FieldValue IN ('var1a','var1b','var1c',etc)
productFilterNode.AddConditions(new Condition("FieldName", myKVP.Key),
OrCondition.Create("FieldValue", myKVP.Value.ToArray()));
}
}
// create result query by JoinNode productDetailNode
QueryDesigner queryDesigner = new QueryDesigner(db, productDetailNode).
OrderBy(new Ordering("ProductTypeName"));
return queryDesigner.Cast<ProductDetail>();
}

Resources