Entity Framework - Handle null value in Linq - c#

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();

Related

how do i ignore tables with no rows and return values from other tables in linq

I'm working on this conference app where I have to return certain values from the different table using join queries using LINQ
from a in db.ApplySchedule
join b in db.userdetails on a.UserID equals b.UserId
join c in db.roomdetails on a.RoomID equals c.RoomId
join d in db.VideoFiles on a.RoomID equals d.RoomId where d.IsActive == true || d.IsActive==false
join e in db.ImageFiles on a.RoomID equals e.RoomId where e.IsActive == true|| e.IsActive==false
where EntityFunctions.TruncateTime(a.MDate) == EntityFunctions.TruncateTime(DateTime.Now) && a.RoomID == id
&& a.Status == true
select new ShedulerViewModel
{
Id = a.BookingID,
UserId = a.UserID,
Uname = b.UserName,
RoomId = a.RoomID,
Rname = c.RoomName.ToUpper(),
Organizer = a.SubjectDetail,
Date = a.MDate,
FromTime = a.start_date,
ToTime = a.end_date,
//Accesseries = a.Accesseries,
attend = a.Attend,
VideoID = d.RoomId,
VideoPath = d.FilePath,
videoIsActive= d.IsActive,
ImageId = e.RoomId,
ImagePath = e.FilePath,
ImageIsActive = e.IsActive
};
Here is the problem, I'm able to get the values if the last two tables db.imagefiles and db.videofiles has matching values but incase it doesn't I'm getting 0 value from all the other tables even though there are rows with matching id, how do I overcome this? I want to pass value even if the video and image tables have no rows.

How do you Left join 'Is Not Null' using linq?

I am having some issues getting my LINQ statement to work. I am left joining a table, secondTable, where one of the columns can be null but I only need the records where this column is not null. I'm not sure how to get the following into a LINQ expression
LEFT JOIN secondTable b ON a.ID = b.oneTableID AND b.name IS NOT NULL
So far my LINQ is:
var list = await (from one in dbRepository.oneTable
join two in dbRepository.secondTable
on new { name = one.name, phone = one.phone, height = { is not null} } equals new
{ name = two.name, phone = two.phone, height = two.height
into temp
from two in temp.DefaultIfEmpty()
select new.....
Any Ideas?
EDIT 1: I was able to find a solution.
var list = await (from one in dbRepository.oneTable
join two in dbRepository.secondTable
on new { name = one.name, phone = one.phone, height = false } equals new
{ name = two.name, phone = two.phone, height = string.IsNullOrEmpty(two.height)}
into temp
from two in temp.DefaultIfEmpty()
select new.....
You have to use SelectMany possibility to create LEFT JOIN:
var query =
from one in dbRepository.oneTable
from two in dbRepository.secondTable
.Where(two => two.name = one.name && two.phone == one.phone
&& two.height != null)
.DefaultIfEmpty()
select new.....
Try this one:
var list = await (from one in dbRepository.oneTable
join two in dbRepository.secondTable
on new { name = one.name, phone = one.phone}
equals new
{ name = two.name, phone = two.phone}
into temp
from two in temp.DefaultIfEmpty()
where one.height == null || one.height = two.height
select new.....

Ho to Convert a Uint to Nullable Int in a EF Query

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;

C# - Using Linq get data if null value exist in query

I have two datatables,
var userList1 = from myRow in dt.AsEnumerable()
where myRow.Field<bool?>("IsActive1") == null
? true
: myRow.Field<bool?>("IsActive1") == true
select myRow;
var userList2 = from myRow in dt1.AsEnumerable()
select myRow;
dt1 table shows like this,
Using this Linq query,
var objUserSetUp1 = (from A in userList1
join B in userList2
on new
{
UserId = A.Field<Int64?>("Id") == null
? 0
: A.Field<Int64>("Id")
}
equals new
{
UserId = B.Field<Int64?>("UserId") == null
? 0
: B.Field<Int64>("UserId")
}
select new
{
UserId = A.Field<Int64>("Id"),
FirstName = A.Field<string>("FirstName"),
SurName = A.Field<string>("SurName"),
Computer_Name = A.Field<string>("Computer_Name"),
IP_Address = A.Field<string>("IP_Address"),
LogInTime = A.Field<string>("LogInTime") == null
? "UnKnown"
: A.Field<string>("LogInTime"),
UserName = A.Field<string>("UserName"),
Password = A.Field<string>("Password"),
login_Id = A.Field<Int64?>("login_Id") == null
? 0 :
A.Field<Int64?>("login_Id"),
docCount = B.Field<Int64>("docCount")
}).ToList();
How can I get if UserId is null also want to take docCout field value too. How can I do this inside the query?
I think you need a Left Outer Join, where the default value for the outer join (ie when no matching record exists) is the userList2 entry where Field("UserId") is null.
See below (untested, but you get the idea!):
var objUserSetUp1 = (from A in userList1
join B in userList2
on A.Field<Int64?>("Id") equals B.Field<Int64?>("UserId")
into BGroup
from C in BGroup.DefaultIfEmpty(userList2.Single(u => u.Field<Int64?>("UserId") == null))
select new
{
UserId = A.Field<Int64>("Id"),
FirstName = A.Field<string>("FirstName"),
SurName = A.Field<string>("SurName"),
Computer_Name = A.Field<string>("Computer_Name"),
IP_Address = A.Field<string>("IP_Address"),
LogInTime = A.Field<string>("LogInTime") == null
? "UnKnown"
: A.Field<string>("LogInTime"),
UserName = A.Field<string>("UserName"),
Password = A.Field<string>("Password"),
login_Id = A.Field<Int64?>("login_Id") == null
? 0 :
A.Field<Int64?>("login_Id"),
docCount = C.Field<Int64>("docCount")
}).ToList();

Union Two Linq Queries

I have two LinqToSql queries that return result sets:
var grResults = (from g in ctx.GeneralRequests
join rt in ctx.RequestTypes on g.RequestTypeId equals rt.RequestTypeId
join sub in ctx.Logins on g.SubmitterStaffId equals sub.LoginId
join onb in ctx.Logins on g.OnBehalfOfStaffId equals onb.LoginId
where sub.GadId == gadId
select new
{
Status = "Submitted",
RequestId = g.GeneralRequestId,
Submitter = sub.UserName,
OnBehalf = (onb == null ? string.Empty : onb.UserName),
RequestType = (rt == null ? string.Empty : rt.Description),
ProjectName = (g == null ? string.Empty : g.ProjectName) ,
Comments = (g == null ? string.Empty : g.Comments),
LastUpdate = g.LastUpdateDate
});
var grdResults = (from gd in ctx.GeneralRequestDrafts
join rt in ctx.RequestTypes on gd.RequestTypeId equals rt.RequestTypeId
into tempRequestTypes
from rt1 in tempRequestTypes.DefaultIfEmpty()
join onb in ctx.Logins on gd.OnBehalfOfStaffId equals onb.LoginId
into tempOnBehalf
from onb1 in tempOnBehalf.DefaultIfEmpty()
join sub in ctx.Logins on gd.SubmitterStaffId equals sub.LoginId
where sub.GadId == gadId
select new
{
Status = "Draft",
RequestId = gd.GeneralRequestDraftId,
Submitter = sub.UserName,
OnBehalf = (onb1 == null ? string.Empty : onb1.UserName),
RequestType = (rt1 == null ? string.Empty : rt1.Description),
ProjectName = (gd.ProjectName == null ? string.Empty : gd.ProjectName),
Comments = (gd.Comments == null ? string.Empty : gd.Comments),
LastUpdate = gd.LastUpdateDate
});
The problem is when I try to Union them.
var results = grResults.Union(grdResults).OrderByDescending(r => r.LastUpdate);
This returns no records even though the two individual queries do.
Since the 2 queries don't appear to rely on each other just execute both and union the results of each if you are just trying to get a single list.
var results = grResults.ToList().Union(grdResults.ToList())
.OrderByDescending(r => r.LastUpdate);

Categories