INNER JOIN 3 Data Tables using LINQ - c#

Trying to use LINQ to join three datatables table1, table2, table3. Table1 and table2 joined on 2 condition and table 1 and table 3 joined on 1 condition. Following is my code. But I am getting an exception saying that
"Unable to cast object of type 'System.DBNull' to type 'System.String'."
Below is my code:
var result = from cust in tblCust.AsEnumerable()
join mat in tblMat.AsEnumerable()
new { coil_id = (string)cust["coil_id"], order_id = (string)cust["order_id"] }
equals
new { coil_id = (string)mat["PIECE_ID"], order_id = (string)mat["PRODUCTION_ORDER_ID"] }
join parts in tblParts.AsEnumerable() on (string)mat["PIECE_ID"] equals (string)parts["ProdCoilNo"]
select new
{
coil_id = mat["PIECE_ID"],
order_id = mat["PRODUCTION_ORDER_ID"],
part = parts["PartNumber"],
gauge = mat["THICKNESS"],
width = mat["WIDTH"],
weight = mat["WEIGHT"],
code = mat["MATERIAL_BLOCK_STATE"],
requestor_comment = cust["requestor_comment"],
requestor = cust["requestor"],
updated_by_comment = cust["updated_by_comment"],
updated_by_user = cust["updated_by_user"]
};
I an getting an exception near (string)parts["ProdCoilNo"]

Use the coalesce operator for the field containing null to replace with empty string
Like this:
coil_id = mat["PIECE_ID"] ?? String.Empty,

Use the coalesce operator
var result = from cust in tblCust.AsEnumerable()
join mat in tblMat.AsEnumerable()
new { coil_id = (string)cust["coil_id"], order_id = (string)cust["order_id"] }
equals
new { coil_id = (string)mat["PIECE_ID"], order_id = (string)mat["PRODUCTION_ORDER_ID"] }
join parts in tblParts.AsEnumerable() on (string)mat["PIECE_ID"] equals (string)parts["ProdCoilNo"]
select new
{
coil_id = mat["PIECE_ID"]?? String.Empty,
order_id = mat["PRODUCTION_ORDER_ID"]?? String.Empty,
part = parts["PartNumber"]?? String.Empty,
gauge = mat["THICKNESS"]?? String.Empty,
width = mat["WIDTH"]?? String.Empty,
weight = mat["WEIGHT"]?? String.Empty,
code = mat["MATERIAL_BLOCK_STATE"]?? String.Empty,
requestor_comment = cust["requestor_comment"]?? String.Empty,
requestor = cust["requestor"]?? String.Empty,
updated_by_comment = cust["updated_by_comment"]?? String.Empty,
updated_by_user = cust["updated_by_user"]?? String.Empty
};

Related

How to use result of first join in second join in LINQ to SQL

I have list table with 2 record. List A and List B. List A has 4 tasks in Task table and List B has 2 tasks in Task table. Task 1 of List A has two time log entries in TimeLog table.No foreign key used.
Now Consider the following code.
var objs = from project_task_list in modelRepository.Get()
join project_task in projectTaskRepository.Get() on project_task_list.ListId equals project_task.ListId into project_task_result
join project_task_timelog in projectTaskTimeLogRepository.Get() on project_task.TaskId equals project_task_timelog.TaskId into project_task_timelog_result
where project_task_list.ProjectId == project_id
select new ProjectTaskListModel
{
ListId = project_task_list.ListId,
ProjectId = project_task_list.ProjectId ?? 0,
ListName = project_task_list.ListName,
ListStartDate = project_task_list.ListStartDate,
ListEndDate = project_task_list.ListEndDate,
ListStatusId = project_task_list.ListStatusId ?? 0,
ListSortOrder = project_task_list.ListSortOrder ?? 0,
ListTasksEstimatedHours = project_task_result.Sum(x => x.TaskEstimatedHours) ?? 0,
ListTasksTimeLogTotalMinutes = project_task_timelog_result.Sum(x => x.LogMinutes) ?? 0
};
I want to use result of one join in another join but i am having following syntax error.
I have also tried the following code.
var objs = from project_task_list in modelRepository.Get()
join project_task in projectTaskRepository.Get() on project_task_list.ListId equals project_task.ListId into project_task_result
from project_task in project_task_result.DefaultIfEmpty()
join project_task_timelog in projectTaskTimeLogRepository.Get() on project_task.TaskId equals project_task_timelog.TaskId into project_task_timelog_result
where project_task_list.ProjectId == project_id
select new ProjectTaskListModel
{
ListId = project_task_list.ListId,
ProjectId = project_task_list.ProjectId ?? 0,
ListName = project_task_list.ListName,
ListStartDate = project_task_list.ListStartDate,
ListEndDate = project_task_list.ListEndDate,
ListStatusId = project_task_list.ListStatusId ?? 0,
ListSortOrder = project_task_list.ListSortOrder ?? 0,
ListTasksEstimatedHours = project_task_result.Sum(x => x.TaskEstimatedHours) ?? 0,
ListTasksTimeLogTotalMinutes = project_task_timelog_result.Sum(x => x.LogMinutes) ?? 0
};
Syntax error gone but the problem is it is returning 6 records while i only have 2 records in list table. What am i doing wrong? Thanks in advance.
I have figured it out my self. All i need was GROUP BY clause in LINQ. Here is the final query.
var objs = from project_task_list in modelRepository.Get()
join project_task in projectTaskRepository.Get() on project_task_list.ListId equals project_task.ListId into project_task_result
from project_task in project_task_result.DefaultIfEmpty()
join project_task_timelog in projectTaskTimeLogRepository.Get() on project_task.TaskId equals project_task_timelog.TaskId into project_task_timelog_result
from project_task_timelog in project_task_timelog_result.DefaultIfEmpty()
where project_task_list.ProjectId == project_id
group new { project_task_list, project_task, project_task_timelog } by new
{
project_task_list.ListId,
project_task_list.ProjectId,
project_task_list.ListName,
project_task_list.ListStartDate,
project_task_list.ListEndDate,
project_task_list.ListStatusId,
project_task_list.ListSortOrder
} into group_result
select new ProjectTaskListModel
{
ListId = group_result.Key.ListId,
ProjectId = group_result.Key.ProjectId ?? 0,
ListName = group_result.Key.ListName,
ListStartDate = group_result.Key.ListStartDate,
ListEndDate = group_result.Key.ListEndDate,
ListStatusId = group_result.Key.ListStatusId ?? 0,
ListSortOrder = group_result.Key.ListSortOrder ?? 0,
ListTasksEstimatedHours = group_result.Sum(x => x.project_task.TaskEstimatedHours) ?? 0,
ListTasksTimeLogTotalMinutes = group_result.Sum(x => x.project_task_timelog.LogMinutes) ?? 0
};

How to convert to Linq

How to convert the following query into linq
SELECT
a.ProductId,
a.Name,
a.Description,
b.Quoteid,
b.Productid,
b.Quantity,
b.OriginalPrice
FROM
Products AS a
LEFT JOIN
QuoteDtails AS b
ON a.ProductId = b.ProductId
AND b.QuoteId = 200;
Don't know where to add the AND condition.
Thanks and regards
You can try this linq if you want to write LEFT JOIN of linq, you need to add
into [temp collection] from [Left join talbe collection] in [temp collection].DefaultIfEmpty()
after Linq join
look like this.
from ss in Products
join aa in QuoteDtails
on ss.ProductId equals aa.ProductId into temp
from ds in temp.DefaultIfEmpty()
where ds.QuoteId = 200
select new
{
ProductId_P = ss.ProductId,
Name = ss.Name,
Description = ss.Description,
Quoteid = ds.Quoteid,
Productid_Q = ds.Productid,
Quantity = ds.Quantity,
OriginalPrice = ds.OriginalPrice
}
You can add AND condition in your LINQ query like this :
var res = from p in products
join q in quoteDtails on new { Criteria1 = p.ProductID, Criteria2 = 200 } equals new { Criteria1 = q.Productid, Criteria2 = q.Quoteid }
select new
{
ProductId_P = p.ProductID,
Name = p.Name,
Description = p.Description,
Quoteid = q.Quoteid,
Productid_Q = q.Productid,
Quantity = q.Quantity,
OriginalPrice = q.OriginalPrice
};

Duplicate values on join linq

I am having some problem with the results, I get duplicates instead of two with different values on the join. The db contains those two values but one of them has different value inside the text field, how come I get duplicates, the only thing that is same is the CompanyPageId).
var query = (from pageEducation in _context.PageEducations
join companyPage in _context.Pages on pageEducation.CompanyPageId equals companyPage.Id into p
from companyPage in p.DefaultIfEmpty()
where pageEducation.PageId == pageId
select new PageEducation
{
Id = pageEducation.Id,
PageId = pageEducation.PageId,
CompanyPageId = pageEducation.CompanyPageId,
CustomCompany = pageEducation.CustomCompany,
CompanyPage = companyPage != null ? new Page {Name = companyPage.Name, Id = companyPage.Id} : null,
Education = pageEducation.Education
}).ToList();
My table looks like this:
CompanyPageId, education
33 edu1
33 edu2
and the result is list with two items but duplicates.
WHen i run this query in SQL i dont get any duplicates:
select * from Page_Educations
left join Pages on page_Educations.CompanyPageId = pages.Id
where page_Educations.PageId = 10
It even working when I run the linq in LinqPad
var query = from pageEducation in Page_Educations
join companyPage in Pages on pageEducation.CompanyPageId equals companyPage.ID into p
from companyPage in p.DefaultIfEmpty()
where pageEducation.PageId == 10
select new
{
Id = pageEducation.Id,
PageId = pageEducation.PageId,
CompanyPageId = pageEducation.CompanyPageId,
CustomCompany = pageEducation.CustomCompany,
CompanyPage = companyPage != null ? new {Name = companyPage.Name, Id = companyPage.ID} : null,
Education = pageEducation.Education
};
query.Dump();

linq query to return a string from a list

I have a products table and an activities table.Each product is made up of different activities.What i want is to display a product name,price,etc and the all the activities (i.e all the activities in one column) which are part of that product in a datagrid using linq
Below is my query
using (bungeedbEntities context = new bungeedbEntities())
{
var bookingData = from con in context.bookings
join agn in context.agents on con.main_agent_id equals agn.code
select new POS_LINK.BusinessObjects.Bookings
{
Product = con.product_name,
Activity = String.Join(",", (from con1 in context.bookings
join acp in context.booking_activity on con1.code equals acp.booking_code
join agn in context.agents on con1.main_agent_id equals agn.code
join act in context.activities on acp.activity_code equals act.code
select act.name).ToArray()),
ReservationCode = con.main_agent_voucher,
CostOfSale = 0.00M,
DateOfActivity = (DateTime)con.date_of_activity,
Notes = con.notes,
Quantity = (int)con.pax,
Child_quantity = 0,
Child_cost_percentage = 0,
CostPerPerson = 0.00M,
SubAgentRef = "56789",
SubAgentName = con.sub_agent_name,
ClientName = con.client_name,
MainAgent = agn.agent_name,
Consultant2 = con.sub_agent_consultant
};
return bookingData.ToList();
On running i get the following error- LINQ to Entities does not recognize the method 'System.String Join(System.String, System.String[])' method, and this method cannot be translated into a store expression.
I seem to have run out of ideas anyone with a better solution to this would save me from a lot of head scratching
You need to do it in two steps: first step selects the data, while the second step translates it to a string with string.Join:
var bookingData = (from con in context.bookings
join agn in context.agents on con.main_agent_id equals agn.code
select new { // Construct an anonymous type with the relevant parts
Product = con.product_name,
ActivityData = (from con1 in context.bookings
join acp in context.booking_activity on con1.code equals acp.booking_code
join agn in context.agents on con1.main_agent_id equals agn.code
join act in context.activities on acp.activity_code equals act.code
select act.name),
ReservationCode = con.main_agent_voucher,
DateOfActivity = (DateTime)con.date_of_activity,
Notes = con.notes,
Quantity = (int)con.pax,
SubAgentName = con.sub_agent_name,
ClientName = con.client_name,
MainAgent = agn.agent_name,
Consultant2 = con.sub_agent_consultant
}).AsEnumerable() // Bring this into memory
.Select(p => new POS_LINK.BusinessObjects.Bookings {
Product = p.Product,
Activity = string.Join(", ", p.ActivityData.ToArray()),
ReservationCode = p.ReservationCode,
CostOfSale = 0.00M,
Notes = p.Notes,
Quantity = p.Quantity,
Child_quantity = 0,
Child_cost_percentage = 0,
CostPerPerson = 0.00M,
SubAgentRef = "56789",
SubAgentName = p.SubAgentName,
ClientName = p.ClientName,
MainAgent = p.MainAgent,
Consultant2 = p.Consultant2
});
return bookingData.ToList();
The idea here is simple: first, you construct an anonymous type that has all relevant information, including an enumeration of acc.names, then you force it into memory by calling AsEnumerable(), and finally construct your POS_LINK.BusinessObjects.Bookings objects using LINQ-to-Object, which understands string.Join.

Getting a field value from a LINQ query without Iteration

I have the following query in controller and I want to store a column value in a variable but I am not being able to iterate it. Here is my code:
var srmas = (
from SRMAs in db.SRMAs
join SRMAStatus in db.SRMAStatus on SRMAs.Status equals SRMAStatus.Id
join PurchaseOrders in db.PurchaseOrders on SRMAs.PONumber equals PurchaseOrders.PONumber
join Suppliers in db.Suppliers on PurchaseOrders.SupplierID equals Suppliers.SupplierID
join SRMADetails in db.SRMADetails on SRMAs.Id equals SRMADetails.SRMAId
where(SRMAs.Id == srmaid)
group SRMADetails by new
{
SRMADetails.Id,
SRMADetails.SRMAId,
SRMADetails.SupplierPartNum,
SRMAs.PONumber,
SRMAs.ActualAmount,
SRMAs.ApprovedOn,
SRMAs.Status,
SRMAs.TrackingNumber,
SRMAs.SupplierRMANumber,
SRMAs.RequestedFromSupp,
SRMAs.CreatedOn,
Suppliers.SupplierName,
SRMAStatus.StatusName,
PurchaseOrders.PODate,
PurchaseOrders.suppliersOrderNumber
} into grp
select new
{
grp.Key.Status,
grp.Key.SRMAId,
grp.Key.Id,
grp.Key.PONumber,
grp.Key.SupplierRMANumber,
grp.Key.ActualAmount,
grp.Key.SupplierPartNum,
grp.Key.RequestedFromSupp,
grp.Key.TrackingNumber,
grp.Key.ApprovedOn,
grp.Key.SupplierName,
grp.Key.StatusName,
grp.Key.PODate,
grp.Key.suppliersOrderNumber,
grp.Key.CreatedOn,
Sum = grp.Sum(SRMADetails => SRMADetails.Cost * SRMADetails.QtyReturned)
}
).ToList();
System.Collections.IEnumerable et = (System.Collections.IEnumerable)srmas;
IEnumerator it = et.GetEnumerator();
while (it.MoveNext())
{
SRMA current = (SRMA)it.Current;
Response.Write(current.Status);
}
ViewBag.SRMAs = srmas.Select(srma => new IndexViewModel
{
Id = srma.SRMAId,
SupplierRMANum = srma.SupplierRMANumber,
SRMADetailsID = srma.Id,
PONumber = srma.PONumber,
CreatedOn = srma.CreatedOn,
SupplierName = srma.SupplierName,
SRMAStatus = srma.StatusName,
Status = srma.Status,
suppliersOrderNumber = srma.suppliersOrderNumber,
PODate = srma.PODate,
Sum = srma.Sum,
TrackingNumber = srma.TrackingNumber,
ActualAmount = srma.ActualAmount
}).ToList();
I just want to get Status value of first record. How do I do it?

Categories

Resources