I have the following sql statement that calculate the sum of the column:
select coalesce(SUM(cdin_ActMortgageAmnt),0)
from CDIndex,company
where comp_companyid=cdin_companyid and comp_idcust like '%10319%'
and cdin_Deleted is null and cdin_startunstufdate is not null
and cdin_Status='InProgress'
gives me the output like this:
I tried to convert it to LINQ like this:
var sumation = (from com in db.Companies
join cd in db.CDIndexes on com.Comp_CompanyId equals cd.cdin_CompanyId
where
cd.cdin_Status == "InProgress" &&
cd.cdin_startunstufdate == null &&
cd.cdin_Deleted == null
select new {
sum = cd.cdin_ActMortgageAmnt
}
);
var summ = sumation.Sum(x => x.sum);
When I put tracePoint beside var summ in debug mode it gives me null when i point to it.
What is the problem?
On your case you are using coalesce(SUM(cdin_ActMortgageAmnt),0) because some values of cdin_ActMortgageAmnt can be null and you are giving the default value of 0, you need to do the same in your final query. Something like this when you do the select
cd.cdin_ActMortgageAmnt ?? 0
this query is appropriate your sql query
var sumation =db.Companies.Join(db.CDIndexes,
com=>com.Comp_CompanyId,
cd=>cd.cdin_companyid,
(com,cd)=>new {com,cd})
.Where(x=>x.com.comp_idcust.Contains("10319") && x.cd.cdin_Status== "InProgress" &&
cd.cdin_startunstufdate != null &&
cd.cdin_Deleted == null)
.Select(x=>new
{
sum=x.cd.cdin_ActMortgageAmnt ?? 0
}).ToList()
Here is one way:
var summ = db.Companies.Join(
db.CDIndexes,
cd => cd.cdin_CompanyId,
com => Comp_CompanyId,
(com, cd) => new { com, cd })
.Where(z=>z.com.comp_idcust.Contains("10319")) // Added "LIKE"
.Where(z=>z.cd.cdin_Status == "InProgress")
.Where(z=>z.cd.cdin_startunstufdate != null) // Reversed your condition
.Where(z=>z.cd.cdin_Deleted == null)
.Sum(z=>z.cd.cdin_ActMortgageAmnt);
You can also combine all the Wheres together, but I prefer not to in most cases like this:
var summ = db.Companies.Join(
db.CDIndexes,
cd => cd.cdin_CompanyId,
com => Comp_CompanyId,
(com, cd) => new { com, cd })
.Where(z=>z.com.comp_idcust.Contains("10319") // Added "LIKE"
&& z.cd.cdin_Status == "InProgress"
&& z.cd.cdin_startunstufdate != null // Reversed your condition
&& z.cd.cdin_Deleted == null)
.Sum(z=>z.cd.cdin_ActMortgageAmnt);
Related
In my query I am getting records based on RoleId and LocationId, some times the user may not pass location in that case I want to remove that filter and get information from all locations.
Currently I am doing this way
if(loc > 0)
{
var myResult = (from x in CSDB.Allocations
join s in CSDB.Managers
on x.ManagerId equals s.Id
Where x.RoleId == 2 && s.LocationId == loc
select new
{
x.name,
x.Date
}).ToList();
}
else
{
var myResult = (from x in CSDB.Allocations
join s in CSDB.Managers
on x.ManagerId equals s.Id
Where x.RoleId == 2
select new
{
x.name,
x.Date
}).ToList();
}
I am seeing if I can check if loc is null or not inside the query instead of using if else.
You can do something like this:
Where x.RoleId == 2 && (loc == null || s.LocationId == loc)
Also, you can do smth like this.
Where x.RoleId == 2 && (loc?.Equals(s.LocationId) ?? true)
If loc just int I would prefer to use a little bit changed #Salah Akbari answer:
Where x.RoleId == 2 && (loc == 0 || s.LocationId == loc)
Simply extract your managers and filter them if needed. That way you can as well easily apply more filters and code readability isn't hurt.
var managers = CSDB.Managers.AsQueryable();
if(loc > 0)
managers = managers.Where(man => man.LocationId == loc);
var myResult = from allocation in CSDB.Allocations
join manager in managers on allocation.ManagerId equals manager.Id
where allocation.RoleId == 2
select new
{
allocation.name,
allocation.Date
};
I have the following lambda statement:
var resources = Db.Resource.Where(w => w.ResValue.Any(a => a.ApplicationFk == applicationPk) && w.CategoryFk == (categoryId ?? w.CategoryFk ) && w.IsEditable);
if (cultureIdsMissing!= null)
{
resources = resources.Where(w => w.ResValue.Any(a => cultureIdsMissing.Any(aa => aa == a.CultureFk) && a.Value == string.Empty));
}
This is not returning the result which I want, which is returned by:
SELECT Resource.ResourcePk, Resource.CategoryFk, Resource.Name, Resource.IsEditable, ResValue.ApplicatieFk, ResValue.CultureFk, ResValue.Value
FROM Resource
INNER JOIN ResValue ON Resource.ResourcePk = ResValue.ResourceFk
WHERE (ResValue.ApplicatieFk = 6)
AND (Resource.IsEditable = 1)
AND (ResValue.Value = '')
AND (ResValue.CultureFk = 1 OR ResValue.CultureFk = 2)
Not that cultureIdsMissing is a List containing both the numbers 1 and 2.
What am I missing or doing wrong with the lambda query?
I think you have to remove && w.CategoryFk == (categoryId ?? w.CategoryFk ) from your linq lemda expression. if categoryId = 1 then it will take only records with value 1. So try after remove that. Your linq code should be this.
var resources = Db.Resource.Where(w => w.ResValue.Any(a => a.ApplicationFk == applicationPk)&& w.IsEditable);
if (cultureIdsMissing!= null)
{
resources = resources.Where(w => w.ResValue.Any(a => cultureIdsMissing.Any(aa => aa == a.CultureFk) && a.Value == string.Empty));
}
You should take it from your sql statement :
Db.Resource
.Join(Db.ResValue
, rs => rs.ResourcePk
, resV => resv.resourceFk
, (rs, resv) => new { res = rs, resV = resV })
.Where(w => w.resv.ApplicatieFk == 6
&& w.res ==1
&& resv.Value == string.empty()
&& (resv.CultureFk == 1 || resv.CultureFk == 2))
It's not tested so maybe it won't work on first try.
I would translate the SQL to query comprehension syntax. In general, convert phrases in query comprehension order, use table aliases as range variables (or create range variables), and put unary/overall aggregate functions (such as TOP, DISTINCT or SUM) as function calls outside the whole query. For your SQL,
var ans = from r in Resource
where r.IsEditable == 1
join rv in ResValue on r.ResourcePk equals rv.ResourceFk
where rv.ApplicatieFk == 6 && rv.Value == "" && (rv.CultureFk == 1 || rv.CultureFk == 2)
select new { r.ResourcePk, r.CategoryFk, r.Name, r.IsEditable, rv.ApplicatieFk, rv.CultureFk, rv.Value };
I am getting the following results for
string[] proj = Pid.Split(',');
"1032,1222" --> [0]=1032,[1]=1222
but I want to use in LINQ query. This is my LINQ query. Where to use it and how to use it?
string[] proj = Pid.Split(',');
var data2 = (from p in Db.emp.AsEnumerable()
join r in Db.use on p.EmployeeId equals r.EmployeeId
join q in Db.proo on p.EmployeeId equals q.EmpId
where (q.IsDelete == false && p.IsDelete == false && p.RoleID != 1 && p.RoleID != 2 && q.ProId == Convert.ToInt32(Pid))
select new GroupSelectedModel {
Text = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(p.FirstName + " " + p.LastName),
Value = r.UserId.ToString(),
StatusId = Convert.ToInt32(p.Status)
})
.Distinct().ToList().OrderBy(r => r.Text);
return data2.OrderBy(p => p.StatusId).ToList();
Please check above mentioned code.
When you need IN, you have to invert it, and use Contains(). Your post is not very clear, but I think you're asking for something like this (note you need to use a List instead of an array):
List<string> proj = new List<string>(Pid.Split(','));
where (q.IsDelete == false && p.IsDelete == false && p.RoleID != 1 && p.RoleID != 2 && proj.Contains(q.ProId))
I have following LINQ2SQL Query:
var map =
dbContext.TCPDriverMappings.FirstOrDefault(
c => c.DriverFacilityId == tcpDms.FacilityId &&
c.DriverControlledParameterId == controlledParamId &&
c.DriverValue == value);
All the types are string.
In my DB i have a row, which must be returned by query.
When value="0", controlledParamId =null and FacilityId ="abc" this query returns null, but when i wrote following:
var test = dbContext.TCPDriverMappings.FirstOrDefault(
c => c.DriverFacilityId == "abc" &&
c.DriverControlledParameterId == null &&
c.DriverValue == "0");
test was not null
What am i doing wrong?
P.S. I also tried c.DriverControlledParameterId.Equals(controlledParamId) but it also doesn't work.
The problem is, that LINQ2SQL has a special handling for the expression c.DriverControlledParameterId == null. It is translated to the SQL DriverControlledParameterId IS NULL.
But c.DriverControlledParameterId = controlledParamId is translated to the SQL DriverControlledParameterId = :p1, even when controlledParamId is null. And in SQL DriverControlledParameterId = NULL is undefined and as such never TRUE.
How to fix: Handle the null case specifically:
TCPDriverMapping test;
if(controlledParamId == null)
test = dbContext.TCPDriverMappings.FirstOrDefault(
c => c.DriverFacilityId == "abc" &&
c.DriverControlledParameterId == null &&
c.DriverValue == "0");
else
test = dbContext.TCPDriverMappings.FirstOrDefault(
c => c.DriverFacilityId == "abc" &&
c.DriverControlledParameterId == controlledParamId &&
c.DriverValue == "0");
Or like this:
var test = dbContext.TCPDriverMappings.FirstOrDefault(
c => c.DriverFacilityId == "abc" &&
((controlledParamId == null &&
c.DriverControlledParameterId == null) ||
c.DriverControlledParameterId == controlledParamId) &&
c.DriverValue == "0");
Or like this:
IQueryable<TCPDriverMapping> query =
dbContext.TCPDriverMappings.Where(c => c.DriverFacilityId == "abc" &&
c.DriverValue == "0");
if(controlledParamId == null)
query = query.Where(c => c.DriverControlledParameterId == null);
else
query = query.Where(c => c.DriverControlledParameterId == controlledParamId);
var test = query.FirstOrDefault();
That third option is what I would use. In my opinion, this is the more readable than option 2 and has no repeated code like the first one.
In the below code:
var results = from service
in LogisticsService.GetTransportationModes<CarrierTransportationMode>
(
x => x.CarrierId == carrierRoleId &&
x.ParentTransportationModeId != null &&
!(x is LoadCarrierMode) &&
(x.ParentTransportationMode.TransportationModeStatus != null) &&
x.ParentTransportationMode.TransportationModeStatus.Value != TransportationModeStatus.Inactive
)
//.OrderByDescending(o => o.IsDefault)
//.ThenBy(t => t.ParentTransportationMode.Name)
orderby service.IsDefault descending, service.ParentTransportationMode.Name
select new
{
text = service.ParentTransportationMode.Name,
value = service.ParentTransportationMode.Id
};
If service.IsDefault is null, I need to skip orderby / thenby completely. So the code would execute as if there was no orderby present in the linq like below:
var results = from service
in LogisticsService.GetTransportationModes<CarrierTransportationMode>
(
x => x.CarrierId == carrierRoleId &&
x.ParentTransportationModeId != null &&
!(x is LoadCarrierMode) &&
(x.ParentTransportationMode.TransportationModeStatus != null) &&
x.ParentTransportationMode.TransportationModeStatus.Value != TransportationModeStatus.Inactive
)
select new
{
text = service.ParentTransportationMode.Name,
value = service.ParentTransportationMode.Id
};
I tried to modify the query with conditions like below:
.OrderByDescending(o => o.IsDefault.HasValue ? o.IsDefault : null)
.ThenBy(t => t.IsDefault.HasValue ? t.ParentTransportationMode.Name : null)
orderby !service.IsDefault.HasValue ? null: service.IsDefault descending, service.ParentTransportationMode.Name
But that didn't help.
Do I need to pass any special parameter in the orderby so that the ordering will never happen at all conditionally? any keyword like 'case' or so can be used? If so, how?
Would appreciate any help!.
Thanks!.
As you need to keep the order of the elements with service.IsDefault == null, an easy solution is to split your dataset into two parts (first service.IsDefault == null, second: service.IsDefault != null) sort the second part, then, concat:
var transportationModes = LogisticsService.GetTransportationModes<CarrierTransportationMode>(x =>
x.CarrierId == carrierRoleId &&
x.ParentTransportationModeId != null &&
!(x is LoadCarrierMode) &&
(x.ParentTransportationMode.TransportationModeStatus != null) &&
x.ParentTransportationMode.TransportationModeStatus.Value != TransportationModeStatus.Inactive)
var services = (from service in transportationModes
where service.IsDefault == null
select service).Concat
(from service in transportationModes
where service.IsDefault != null
orderby service.IsDefault descending, service.ParentTransportationMode.Name
select service);
var results = from service in services
select new
{
text = service.ParentTransportationMode.Name,
value = service.ParentTransportationMode.Id
};