I'm trying to Convert the Uint(i_Customer) to a Nullable Int(i_Customer) ID Since one is accepting the Null value and the other ID Doesn't support.
The parent table is Customer(i_Customer) and the Child is Fault(i_customer). Both, I'm Joining them in a EF Query to get the result. But There is an nullreferenceexception was unhandled by user code Exception that's very disturbing. How Would I fix it?
Here is the EF Query:
if (servicelevel == 3)
{
result = (from s in res
join cInfo in custInfo on
s.fault.i_customer equals Convert.ToInt32((int?)cInfo.customers.i_Customer)
where (s.fault.resolved == null) || (s.tasks.assignedto == agent)
orderby s.fault.ispriority descending, s.fault.logtime ascending
select new ActiveFaultResult()
{ Company_Name = cInfo.customers.Company_Name,
//replies = replies,
idFaults = s.fault.idFaults,
hashvalue = s.fault.hashvalue,
responsible = s.fault.responsible,
logtime = s.fault.logtime,
isinternal = s.fault.isinternal,
ispriority = s.fault.ispriority
}).ToList<ActiveFaultResult>();
// var limitresult = result.Take(50);
return result;
}
A normal cast will do
s.fault.i_customer equals (int?)cInfo.customers.i_Customer
Or try this
s.fault.i_customer ?? 0 equals cInfo.customers.i_Customer
You need to use DefaultIfEmpty() to provide outer join so that it can handle null values. See example below:
result = (from s in res
join cInfo in custInfo on s.fault.i_customer equals (int)cInfo.customers.i_Customer into A
from cInfo in A.DefaultIfEmpty()
where (s.fault.resolved == null) || (s.tasks.assignedto == agent)
orderby s.fault.ispriority descending, s.fault.logtime ascending
select new ActiveFaultResult()
{
Company_Name = cInfo == null? String.Empty: cInfo.customers.Company_Name,
idFaults = s.fault.idFaults,
hashvalue = s.fault.hashvalue,
responsible = s.fault.responsible,
logtime = s.fault.logtime,
isinternal = s.fault.isinternal,
ispriority = s.fault.ispriority
}).ToList<ActiveFaultResult>();
return result;
Related
I have a LINQ query that I'm trying to pass a method into it and then return the results back to the select statement.
There are no errors being thrown but UpdatedYesterday contains nothing even through GetUpdatedValue(int r) is returning a yes or no. Is a way to get the returned value in the select statement ?
For example
var result = (from r in reportOne
join l in logs on r.id equals l.id into g
select new TestReport
{
UserID = r.UserID,
UpdatedDate = r.UpdatedDate,
UpdatedYesterday = g.Where(x => x.LogDate == r.WorkDate)
.Select(x => GetUpdatedValue(x.updatedYesterday)).FirstOrDefault()
}).ToList();
public string GetUpdatedValue(int r)
{
var value = r > 0 ? "Yes" : "No";
return value;
}
I think that your WorkDate can not be the same as LogDate, it's better to use just date difference, without time.
Try this
var result = (from r in reportOne
join l in logs
on r.Id equals l.Id into lg
from l in lg.DefaultIfEmpty()
where EF.Functions.DateDiffDay(r.WorkDate, r.LogDate )==0
select new TestReport
{
UserID = r.UserID,
UpdatedDate = r.UpdatedDate,
UpdatedYesterday=l.UpdatedYesterday > 0 ? "Yes" : "No"
}).ToList();
but if for some reasons you still want to use your method, the easiest way is to add one extra property to TestReport
public UpdatedYesterdayInt int {get; set;}
code
var query=
.....
select new TestReport
{
UserID = r.UserID,
UpdatedDate = r.UpdatedDate,
UpdatedYesterdayInt=l.UpdatedYesterday
}).ToList();
var result=query.ForEach(i=> i.UpdatedYesterday=GetUpdatedValue(i.UpdatedYesterdayInt));
I am developing a query to grab and join some SQL tables in C# and am having some trouble with grouping and enumerables within the dataset. My query is below. This gives me the data in the format I'm looking for, but it takes way too long when I try to add the enumerated list as indicated below. When I look under the hood I can see it is executing way too many SQL queries. I'd like to get it to just one. Using LinqPad:
void Main()
{
var nightlyRuns = (from a in LoadTestSummaries
join b in LoadTestTestSummaryData
on a.LoadTestRunId equals b.LoadTestRunId
where a.TargetStack == "LoadEnv" &&
a.TestGuid != null &&
a.StartTime != null &&
a.LoadTestRunId != null
orderby a.StartTime
group new {a, b} by new
{
a.TestGuid,
a.Name,
a.Description,
a.StartTime,
a.Duration,
a.NumAgents,
a.NumHosts,
a.PassFail,
a.ResultsFilePath,
a.Splunk
}
into g
let scenarioStart = g.Min(s => s.a.StartTime) ?? g.Min(s => s.a.DateCreated)
let testCases = g.Select(s => s.b)
orderby scenarioStart
select new
{
TestGuid = g.Key.TestGuid,
ScenarioRun = new
{
Name = g.Key.Name,
Description = g.Key.Description,
StartTime = scenarioStart,
Duration = g.Key.Duration,
NumAgents = g.Key.NumAgents,
NumHosts = g.Key.NumHosts,
Result = g.Key.PassFail,
ResultsFilePath = g.Key.ResultsFilePath,
SplunkLink = g.Key.Splunk,
// PROBLEM: Causes too many queries:
TestRuns = from t in testCases select t.TestCaseId
}
}).ToLookup(g => g.TestGuid, g => g.ScenarioRun);
nightlyRuns["ba593f66-695f-4fd1-99c3-71253a2e4981"].Dump();
}
The "TestRuns" line is causing the excessive queries. Any idea what I am doing wrong here?
Thanks for any insight.
Tough answer to test but I think we can avoid the grouping and multiple queries with something like this: (https://msdn.microsoft.com/en-us/library/bb311040.aspx)
var nightlyRuns = (from a in LoadTestSummaries
join b in LoadTestTestSummaryData
on a.LoadTestRunId equals b.LoadTestRunId
where a.TargetStack == "LoadEnv" &&
a.TestGuid != null &&
a.StartTime != null &&
a.LoadTestRunId != null
into testGroup
select new
{
TestGuid = a.TestGuid,
ScenarioRun = new
{
Name = a.TestGuid,
Description = a.Description,
StartTime = a.StartTime ?? a.DateCreated,
Duration = a.Duration,
NumAgents = g.Key.NumAgents,
NumHosts = a.NumHosts,
Result = a.PassFail,
ResultsFilePath = a.ResultsFilePath,
SplunkLink = a.Splunk,
// PROBLEM: Causes too many queries:
TestRuns =testGroup
}
}).OrderBy(x=>x.StartTime).ToLookup(x => x.TestGuid, x => x.ScenarioRun);
nightlyRuns["ba593f66-695f-4fd1-99c3-71253a2e4981"].Dump();
I'm returning anonymouse type from my webapi controller, one of the values I need to be computed by using function. When I'm trying to do this way getting error say "Several actions were found that match request".
Here is how I call GET:
// GET api/Grafik/5
public IHttpActionResult GetGrafik(int id)
{
xTourist t = db.xTourist.Find(id);
var beach = db.xAdres.Find(t.Hotel).Kod;
var result = from a in db.Grafik
join b in db.Excursions on a.Excursion equals b.Kod
join c in db.Dates on a.KodD equals c.KodD
join d in db.Staff on a.Guide equals d.Kod
where c.Date > t.ArrDate && c.Дата < t.DepDate
let pu = from x in db.xPickUp where x.KodP == beach && x.Excursion == b.Kod select x.PickUpTime
orderby c.Date
select new { kodg = a.Kodg, excursion = b.Name, guide = d.GuideName, data = c.Date, pricead = b.Price,
pricech = b.PriceChd, pax = t.Pax, child = t.Ch, paxleft = GetPax(a.Kodg), pickup = pu.FirstOrDefault()};
return Ok(result);
}
And here is the function returning needed value:
public int GetPax(int id)
{
//get pax quota
var pre = db.Grafik.Where(k => k.Kodg == id).Select(p => p.Quota).SingleOrDefault();
if (pre.HasValue && pre.Value > 0)
{
//Get taken pax
var p = (from a in db.Orders where a.Kodg == id & !(a.Cansel == true) select a.Child).Sum();
var c = (from a in db.Orders where a.Kodg == id & !(a.Cansel == true) select a.Pax).Sum();
if (p.HasValue & c.HasValue)
{
return pre.Value - (p.Value + c.Value);
}
else
{
return pre.Value;
}
}
else
{
return 0;
}
}
Web API is seeing two public methods with id as a parameter and it can't figure out which one to execute when you send your request. Looking at your code, there's no need for the helper method GetPax() to be public. Try changing it to private.
private int GetPax(int id) // ...
I found solution. Ok, this could be a bit strange way, but it's working.
public IHttpActionResult GetГрафик(int id)
{
xTourist t = db.xTourist.Find(id);
var beach = db.xAdres.Find(t.Hotel).Kod;
var result = from a in db.Grafik
join b in db.Excursions on a.Excursion equals b.Kod
join c in db.Dates on a.Kodd equals c.Kodd
join d in db.Staff on a.Guidename equals d.Kod
join e in db.Заказы on a.КодГ equals e.КодГ
where c.Дата > t.Датапр && c.Дата < t.Датаотл
let pu = from x in db.xPickUp where x.КодП == beach && x.Excursion == b.Kod select x.PickUpTime
orderby c.Дата
let pl = a.Пребукинг - (e.Child + e.Pax)
select new { kodg = a.КодГ, excursion = b.Название, guide = d.Name, data = c.Дата, pricead = b.Price,
pricech = b.PriceChd, pax = t.Колчел, child = t.Дети, paxleft = pl, pickup = pu.FirstOrDefault()};
return Ok(result);
}
I'm writing two LINQ queries where I use my first query's result set in my second query.
But in some cases when there is no data in the database table my first query returns null,
and because of this my second query fails since wsdetails.location and wsdetails.worklocation are null causing an exception.
Exception:
Object reference not set to an instance of an object
My code is this:
var wsdetails = (from assetTable in Repository.Asset
join userAsset in Repository.UserAsset on
assetTable.Asset_Id equals userAsset.Asset_Id
join subLocationTable in Repository.SubLocation on
assetTable.Sub_Location_Id equals subLocationTable.Sub_Location_ID
where userAsset.User_Id == userCode
&& assetTable.Asset_TypeId == 1 && assetTable.Asset_SubType_Id == 1
select new { workstation = subLocationTable.Sub_Location_Name, location = assetTable.Location_Id }).FirstOrDefault();
result = (from emp in this.Repository.Employee
join designation in this.Repository.Designation on
emp.DesignationId equals designation.Id
where emp.Code == userCode
select new EmployeeDetails
{
firstname = emp.FirstName,
lastname = emp.LastName,
designation = designation.Title,
LocationId = wsdetails.location,
WorkStationName = wsdetails.workstation
}).SingleOrDefault();
As a workaround I can check
if wsdetails == null
and change my second LINQ logic, but I believe there are some ways to handle null values in LINQ itself like the ?? operator.
But I tried this and it didn't work for me.
Any help?
The problem is EF can't translate the null-coalescing operator to SQL. Personally I don't see what's wrong with checking the result with an if statement before executing the next query. However, if you don't want to do that, then because your result is always going to be a single query why not do something like:
var wsdetails = (from assetTable in Repository.Asset
join userAsset in Repository.UserAsset on
assetTable.Asset_Id equals userAsset.Asset_Id
join subLocationTable in Repository.SubLocation on
assetTable.Sub_Location_Id equals subLocationTable.Sub_Location_ID
where userAsset.User_Id == userCode
&& assetTable.Asset_TypeId == 1 && assetTable.Asset_SubType_Id == 1
select new { workstation = subLocationTable.Sub_Location_Name, location = assetTable.Location_Id }).FirstOrDefault();
result = (from emp in this.Repository.Employee
join designation in this.Repository.Designation on
emp.DesignationId equals designation.Id
where emp.Code == userCode
select new EmployeeDetails
{
firstname = emp.FirstName,
lastname = emp.LastName,
designation = designation.Title
}).SingleOrDefault();
result.LocationId = wsdetails != null ? wsdetails.location : "someDefaultValue";
result.WorkStationName = wsdetails != null ? wsdetails.workstation ?? "someDefaultValue";
Instead of the "binary" operator ?? maybe you should use the good old ternary one, ? :, like in
wsdetails != null ? wsdetails.location : null
Try not evaluating the first query, and use it in the second query. This should result in a single SQL statement.
var wsdetails = (from assetTable in Repository.Asset
join userAsset in Repository.UserAsset on
assetTable.Asset_Id equals userAsset.Asset_Id
join subLocationTable in Repository.SubLocation on
assetTable.Sub_Location_Id equals subLocationTable.Sub_Location_ID
where userAsset.User_Id == userCode
&& assetTable.Asset_TypeId == 1 && assetTable.Asset_SubType_Id == 1
select new { workstation = subLocationTable.Sub_Location_Name, location = assetTable.Location_Id });
// wsdetails is still an IEnumerable/IQueryable
result = (from emp in this.Repository.Employee
join designation in this.Repository.Designation on
emp.DesignationId equals designation.Id
where emp.Code == userCode
select new EmployeeDetails
{
firstname = emp.FirstName,
lastname = emp.LastName,
designation = designation.Title,
LocationId = wsdetails.First().location,
WorkStationName = wsdetails.First().workstation
}).SingleOrDefault();
I am using Linq query and call method Like..
oPwd = objDecryptor.DecryptIt((c.Password.ToString())
it will return null value.
Means this will not working.
how I Resolve this.
Thanks..
var q =
from s in db.User
join c in db.EmailAccount on s.UserId equals c.UserId
join d in db.POPSettings
on c.PopSettingId equals d.POPSettingsId
where s.UserId == UserId && c.EmailId == EmailId
select new
{
oUserId = s.UserId,
oUserName = s.Name,
oEmailId = c.EmailId,
oEmailAccId = c.EmailAccId,
oPwd = objDecryptor.DecryptIt(c.Password.ToString()),
oServerName = d.ServerName,
oServerAdd = d.ServerAddress,
oPOPSettingId = d.POPSettingsId,
};
If that is LINQ-to-SQL or Entity Framework. You'll need to break it into steps (as it can't execute that at the DB). For example:
var q = from s in db.User
join c in db.EmailAccount on s.UserId equals c.UserId
join d in db.POPSettings on c.PopSettingId equals d.POPSettingsId
where s.UserId == UserId && c.EmailId == EmailId
select new
{
oUserId = s.UserId,
oUserName = s.Name,
oEmailId = c.EmailId,
oEmailAccId = c.EmailAccId,
oPwd = c.Password,
oServerName = d.ServerName,
oServerAdd = d.ServerAddress,
oPOPSettingId = d.POPSettingsId,
};
then use AsEnumerable() to break "composition" against the back-end store:
var query2 = from row in q.AsEnumerable()
select new
{
row.oUserId,
row.oUserName,
row.oEmailId,
row.oEmailAccId,
oPwd = objDecryptor.DecryptIt(row.oPwd),
row.oServerName,
row.oServerAdd,
row.oPOPSettingId
};
var q = from s in db.User
join c in db.EmailAccount on s.UserId equals c.UserId
join d in db.POPSettings on c.PopSettingId equals d.POPSettingsId
where s.UserId == UserId && c.EmailId == EmailId
select new
{
oUserId = s.UserId,
oUserName = s.Name,
oEmailId = c.EmailId,
oEmailAccId = c.EmailAccId,
oPwd = c.Password,
oServerName = d.ServerName,
oServerAdd = d.ServerAddress,
oPOPSettingId = d.POPSettingsId,
};
foreach (var item in q)
{
item.oPwd = objDecryptor.DecryptIt(row.oPwd),
}
we can use a foreach loop also to update a single property. do not need to select all property in next query.
This has nothing about Linq query. you need to debug method objDecryptor.DecryptIt