How to add table my join tables? ASP.NET MVC - c#

My question is, inside my join of IDs, is it possible to add another column with an ID?
This is what I am trying to do:
My Index:
var orders= db.Orders.ToList();
var colers = db.Colors.ToList();
var result = (from c in orders
join st in colers on c.ID_Orders equals st.id into table1
select new OrderWithColorsViewModel { order =c, colers = table1.ToList()
}).ToList();
return View(result);
My classes:
public partial class Orders
{
public int ID_Orders { get; set; }
public Nullable<System.DateTime> Data_Registo { get; set; }
public string Num_Encomenda { get; set; }
public string Ref_Cliente { get; set; }
}
public partial class Colors
{
public int ID_Orders { get; set; }
public int ID_Line_Color { get; set; }
public string Color{ get; set; }
}
public partial class Quantities
{
public int ID_Orders { get; set; }
public int ID_Line_Color { get; set; }
public int quantity{ get; set; }
}
Of what I am learning right now I have this from my join:
and:
But what I want (I think):
If i am wrong in thinking, correct me, thanks

I leave my solution here for those who need it
var result1 = (from o in order
join c in coler
on o.ID_Programa equals c.ID_Programa into co
group new { o, co } by o.ID_Programa into g
from i in g
select new { order = i.o, colors = i.co }).ToList();
var result2 = (from r1 in result1
from c in r1.colors
join q in quant
on new { orderId = c.ID_Programa, colorlineId = c.ID_Linha_Cor } equals new { orderId = q.ID_Programa, colorlineId = q.ID_Linha_Cor } into p1
from p in p1
join s in statu
on new { orderId = p.ID_Programa, colorlineId = p.ID_Linha_Cor } equals new { orderId = s.ID_Programa, colorlineId = s.ID_Linha_Cor } into q
group new ColorsAndQuantities { coler = c, quant = p1.ToList(), status = q.ToList() } by c.ID_Programa).ToList();
var result = (from r1 in result1
join m in fabric
on r1.order.ID_Programa equals m.ID_Programa into t
from t1 in t
join r2 in result2
on t1.ID_Programa equals r2.Key
select new OrdersColorsViewModel
{
order = r1.order,
malhas = t1,
colers = r2.ToList()
}).ToList();

Related

C# LINQ left join 3 Tables/Lists

I am looking to join 3 tables which I am getting as List of objects. These are my three tables:
Employee
Department
Category
Employee DepartmentID and CategoryID is used to join Department and Category Table.
This is how my Linq Join looks
var result = from e in Employee.GetAllEmployees()
join d in Department.GetAllDepartments() on e.DepartmentID equals d.ID
join c in Cateory.GetAllCategories() on e.CategoryID equals c.ID
into eGroup
from c in eGroup.DefaultIfEmpty()
select new
{
Employee =e,
Department = d ==null? new Department() : d,
Cateory = c
};
My issue here is that I am getting two different rows for Employee ID = 1 and that's because of two different Categories for ID =1
I would like to get both categories in the same Employee node. Basically two categories for Employee ID = 1.
Expected Result:
CategoryA and CategoryB is tied to Employee Mark.
How do I achieve that?
Thanks for the help !
Here is the code to reproduce what I have so far.
class Program
{
static void Main(string[] args)
{
var result = from e in Employee.GetAllEmployees()
join d in Department.GetAllDepartments() on e.DepartmentID equals d.ID
join c in Cateory.GetAllCategories() on e.CategoryID equals c.ID
into eGroup
from c in eGroup.DefaultIfEmpty()
select new
{
Employee =e,
Department = d ==null? new Department() : d,
Cateory = c
};
Console.WriteLine("Hello World!");
Console.ReadLine();
}
public class Employee
{
public int EmployeeID { get; set; }
public string Name { get; set; }
public int DepartmentID { get; set; }
public int CategoryID { get; set; }
public static List<Employee> GetAllEmployees()
{
return new List<Employee>()
{
new Employee { EmployeeID = 1, Name = "Mark", DepartmentID = 1, CategoryID = 1 },
};
}
}
public class Department
{
public int ID { get; set; }
public string DepartmentName { get; set; }
public static List<Department> GetAllDepartments()
{
return new List<Department>()
{
new Department { ID = 1, DepartmentName = "TECH"},
new Department { ID = 2, DepartmentName = "HR"},
};
}
}
public class Cateory
{
public int ID { get; set; }
public string CategoryName { get; set; }
public static List<Cateory> GetAllCategories()
{
return new List<Cateory>()
{
new Cateory { ID = 1, CategoryName = "CategoryA"},
new Cateory { ID = 1, CategoryName = "CategoryB"},
new Cateory { ID = 2, CategoryName = "CategoryC"},
};
}
}
}
I don't have a way of testing this really but you should be able to do a left join by updating your query
var result = from e in Employee.GetAllEmployees()
join d in Department.GetAllDepartments() on e.DepartmentID equals d.ID into d_def
from d in d_def.DefaultIfEmpty()
join c in Cateory.GetAllCategories() on e.CategoryID equals c.ID into c_def
from c in c_def.DefaultIfEmpty())
select new
{
Employee =e,
Department = d ==null? new Department() : d,
Cateory = c
};
Here are your results. The two employer have the same ID number

How to provide SQL subquery in LINQ

What is the best practice to convert Sub Query into LINQ,
for example I use this following query :
select VerID = (select top 1 x.INTERNALPACKINGSLIPID from
CUSTPACKINGSLIPVERSION x where a.RECID = x.CUSTPACKINGSLIPJOUR
order by x.VERSIONDATETIME desc),
c.LINENUM, c.RECID, *
from CUSTPACKINGSLIPJOUR a inner join CUSTPACKINGSLIPTRANS c
on a.PACKINGSLIPID = c.PACKINGSLIPID
I simulated you database with classes to get the syntax correct. Make modifications as necessary. There is no best method. Some people like using Where instead of joins. I like joins.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<CUSTPACKINGSLIPVERSIONs> CUSTPACKINGSLIPVERSION = new List<CUSTPACKINGSLIPVERSIONs>();
List<CUSTPACKINGSLIPJOURs> CUSTPACKINGSLIPJOUR = new List<CUSTPACKINGSLIPJOURs>();
List<CUSTPACKINGSLIPTRANSs> CUSTPACKINGSLIPTRANS = new List<CUSTPACKINGSLIPTRANSs>();
var VerId = (from vId in CUSTPACKINGSLIPVERSION
join slipId in CUSTPACKINGSLIPJOUR on vId.INTERNALPACKINGSLIPID equals slipId.RECID
join cId in CUSTPACKINGSLIPTRANS on vId.INTERNALPACKINGSLIPID equals cId.PACKINGSLIPID
select new { vid = vId, slipId = slipId, cId = cId })
.GroupBy(x => x.vid.VERSIONDATETIME)
.OrderBy(x => x.Key)
.FirstOrDefault()
.Select(x => new { linenum = x.cId.LINENUM, recid = x.cId.RECID })
.ToList();
}
}
public class CUSTPACKINGSLIPVERSIONs
{
public int INTERNALPACKINGSLIPID { get; set; }
public DateTime VERSIONDATETIME { get; set; }
}
public class CUSTPACKINGSLIPJOURs
{
public int RECID { get; set; }
public int PACKINGSLIPID { get; set; }
}
public class CUSTPACKINGSLIPTRANSs
{
public int PACKINGSLIPID { get; set; }
public int LINENUM { get; set; }
public int RECID { get; set; }
}
}
You have this in your query and I am assuming it is a typo: a.RECID = x.CUSTPACKINGSLIPJOUR because CUSTPACKINGSLIPJOUR is the collection name. Therefore, I used SomeId instead. But this should give you the idea:
Do a subquery within the projection. You will also need to order by descending and then take the first record-this will be like top 1. Here is the query:
var query = from a in CUSTPACKINGSLIPJOUR
join c in CUSTPACKINGSLIPTRANS on a.PACKINGSLIPID equals c.PACKINGSLIPID
select new
{
VerID = (from x in CUSTPACKINGSLIPVERSION
where a.RECID == x.SomeId select x)
.OrderByDescending(o => o.VERSIONDATETIME)
.First().INTERNALPACKINGSLIPID,
c.LINENUM,
c.RECID
};
You can test it with the following collections:
var CUSTPACKINGSLIPJOUR = new List<CUSTPACKINGSLIPJOUR> { new CUSTPACKINGSLIPJOUR { PACKINGSLIPID = 1, RECID = 1 },
new CUSTPACKINGSLIPJOUR { PACKINGSLIPID = 2, RECID = 2 }};
var CUSTPACKINGSLIPTRANS = new List<CUSTPACKINGSLIPTRANS>
{
new CUSTPACKINGSLIPTRANS { LINENUM = 1, RECID = 1, PACKINGSLIPID = 1 }
};
var CUSTPACKINGSLIPVERSION = new List<CUSTPACKINGSLIPVERSION>
{
new CUSTPACKINGSLIPVERSION { INTERNALPACKINGSLIPID = 1, SomeId = 1, VERSIONDATETIME = DateTime.Today.AddDays(-1) },
new CUSTPACKINGSLIPVERSION { INTERNALPACKINGSLIPID = 2, SomeId = 1, VERSIONDATETIME = DateTime.Today }
};
It will be the same query if you use a DbSet<T>.
Suppose you have those setup:
public class TBL_CUSTPACKINGSLIPVERSION
{
public int CUSTPACKINGSLIPVERSION_ID { get; set; }
public int INTERNALPACKINGSLIPID { get; set; }
public DateTime VERSIONDATETIME { get; set; }
}
public class TBL_CUSTPACKINGSLIPJOUR
{
public int RECID { get; set; }
public int PACKINGSLIPID { get; set; }
}
public class TBL_CUSTPACKINGSLIPTRANS
{
public int PACKINGSLIPID { get; set; }
public int LINENUM { get; set; }
public int RECID { get; set; }
}
var CUSTPACKINGSLIPVERSION = new List<TBL_CUSTPACKINGSLIPVERSION>();
var CUSTPACKINGSLIPJOUR = new List<TBL_CUSTPACKINGSLIPJOUR>();
var CUSTPACKINGSLIPTRANS = new List<TBL_CUSTPACKINGSLIPTRANS>();
Then you can setting up the combined query as given in example below (assumed CUSTPACKINGSLIPVERSION_ID is the identity key which used in comparison between CUSTPACKINGSLIPJOUR & CUSTPACKINGSLIPTRANS):
var query = (from a in CUSTPACKINGSLIPJOUR
join c in CUSTPACKINGSLIPTRANS
on a.PACKINGSLIPID equals c.PACKINGSLIPID
select new {
VerID = (from x in CUSTPACKINGSLIPVERSION
where a.RECID == x.CUSTPACKINGSLIPVERSION_ID // should be an identity column/primary key to compare with
orderby x.VERSIONDATETIME descending
select x).FirstOrDefault().INTERNALPACKINGSLIPID,
c.LINENUM,
c.RECID
}).ToList();
Note that your query includes * at the end of SELECT statement which may indicate the query will return all records from both tables involved in join clause. If you want to return entire records of CUSTPACKINGSLIPJOUR only but not return all CUSTPACKINGSLIPTRANS, include a into the select new statement (incorporates SQL usage of a.*):
select new {
VerID = (from x in CUSTPACKINGSLIPVERSION
where a.RECID == x.CUSTPACKINGSLIPVERSION_ID // should be an identity column/primary key to compare with
orderby x.VERSIONDATETIME descending
select x).FirstOrDefault().INTERNALPACKINGSLIPID,
c.LINENUM,
c.RECID,
a // used if you want to return all records from CUSTPACKINGSLIPJOUR
}).ToList();

Unable to convert AnonymousType#1 ti IEnumerable

I have declared a model in my .cs page
public class InstrumentDetails
{
public long PullNo { get; set; }
public string Description { get; set; }
public int New { get; set; }
public int LN { get; set; }
public int PR { get; set; }
public int Any { get; set; }
}
After that i am retrieving data like this way :
IEnumerable<InstrumentDetails> instrumentdetails = (from p in NemcDb.tblPulls
join
pi in NemcDb.tblPullInstruments
on
p.PullId equals pi.PullId
join
i in NemcDb.tblInstruments
on
pi.InstrumentCode equals i.InstrumentCode
select new
{
PullNo = p.PullNo.Value,
InstrumentType = i.Description,
New = pi.NewQuantity,
LN = pi.LNQuantity,
PR = pi.UsedQuantity,
Any = pi.AnyQuantity
}).Where(i => i.PullNo.ToString() == item);
But it gives me the error
Cannot convert 'System.Linq.IQueryable<AnonymousType#1>' to 'System.Collections.Generic.IEnumerable<>'. An explicit conversion exists (are you missing a cast?)
Where am I wrong?...I couldn't get it through....Please help.
You don't tell that you want an object of type InstrumentDetails, you create an anonymous type. Change select new { ... into select new InstrumentDetails { ... and then also call ToList(), ToEnumerable() or ToArray() in the end so the query is actually run.
The answer would be :
IEnumerable<InstrumentDetails> instrumentdetails = (from p in NemcDb.tblPulls
join
pi in NemcDb.tblPullInstruments
on
p.PullId equals pi.PullId
join
i in NemcDb.tblInstruments
on
pi.InstrumentCode equals i.InstrumentCode
select new InstrumentDetails
{
PullNo = p.PullNo.Value,
InstrumentType = i.Description,
New = pi.NewQuantity,
LN = pi.LNQuantity,
PR = pi.UsedQuantity,
Any = pi.AnyQuantity
}).Where(i => i.PullNo.ToString() == item).ToList();
}
How Silly of me............

Insert results of 2 collections into a new model

I have a wpf c# app.
I have to list collections.
I want to join these 2 lists and return the results that match a criteria.
I want the result to be loaded into a new list/model.
This is my code so far:
var Results = from j in res
join c in Customer.GetBaseData() on j.CustomerRef equals c.CustomerRef
where j.JobStatusRef == jobStatusRef
select new {
c.CustomerRef,
c.CustomerId,
c.Add1,
c.Town,
c.FName,
c.SName,
j.DateReq,
j.JobId,
j.JobRef,
j.JobStatus
};
This is my destination model:
public class CustomerJobs
{
public int JobId { get; set; }
public string CustomerRef { get; set; }
public string DateReq { get; set; }
public string JobRef { get; set; }
public string JobStatus { get; set; }
public int CustomerId { get; set; }
public string SName { get; set; }
public string FName { get; set; }
public string Add1 { get; set; }
public string Town { get; set; }
}
I do not know how to do this final step?
Instead of creating an anonymous type with new { ... }, directly use your model in the select:
var Results = from j in res
join c in Customer.GetBaseData() on j.CustomerRef equals c.CustomerRef
where j.JobStatusRef == jobStatusRef
// Note the "new CustomerJobs" part.
select new CustomerJobs {
c.CustomerRef,
c.CustomerId,
c.Add1,
c.Town,
c.FName,
c.SName,
j.DateReq,
j.JobId,
j.JobRef,
j.JobStatus
};
When you select in linq you can specify the type of the object like:
var Results = from j in res
join c in Customer.GetBaseData() on j.CustomerRef equals c.CustomerRef
where j.JobStatusRef == jobStatusRef
select new CustomerJobs {
CustomerRef = c.CustomerRef,
CustomerId = c.CustomerId,
Add1 = c.Add1,
Town = c.Town,
FName = c.FName,
SName = c.SName,
DateReq = j.DateReq,
JobId = j.JobId,
JobRef = j.JobRef,
JobStatus = j.JobStatus
};

C# EntityFramework Join all records

I created an EF Join. The frameStart has 19 records and frameEnd has 42 records, but when I do the join ( framing ), there are only 10 records. I believe there are only 10 records because it is joining records that can be grouped with the matching key. The code is below. How do I make it so that when it does the join, I get a list of all the records, even the ones that do not "match"?
public class s84_Report_FrameLabor
{
public int CustomerID { get; set; }
public string CustomerName { get; set; }
public int SubdivisionID { get; set; }
public string SubdivisionName { get; set; }
public int LotNumber { get; set; }
public string InstallManagerStart { get; set; }
public string InstallManagerComplete { get; set; }
public DateTime FrameLaborStart { get; set; }
public DateTime FrameLaborComplete { get; set; }
public int Duration { get; set; }
/*
Frame Labor Start ------ Product ID: 26
Frame Labor Complete ------ Product ID: 8
*/
public static List<s84_Report_FrameLabor> getDurationReport()
{
using (var context = PrimaryConnection.returnNewConnection())
{
var frameStart = (from c in context.s84_Schedule
where c.ProductID == 26 && c.Completed == false
select new
{
CustomerID = c.CustomerID,
CustomerName = c.s84_Customer.CustomerName,
SubdivisionID = c.SubdivisionID,
SubdivisionName = c.s84_Subdivision.SubdivisionName,
LotNumber = c.LotNumber,
FrameLaborStart = c.CustomerExpectedDate
}).ToList();
var frameEnd = (from c in context.s84_Schedule
where c.ProductID == 8 && c.Completed == false
select new
{
CustomerID = c.CustomerID,
SubdivisionID = c.SubdivisionID,
LotNumber = c.LotNumber,
FrameLaborComplete = c.CustomerExpectedDate
}).ToList();
var framing = from c in frameStart
join e in frameEnd on new { c.CustomerID, c.SubdivisionID, c.LotNumber } equals new { e.CustomerID, e.SubdivisionID, e.LotNumber }
select new s84_Report_FrameLabor
{
CustomerID = c.CustomerID,
CustomerName = c.CustomerName,
SubdivisionID = c.SubdivisionID,
SubdivisionName = c.SubdivisionName,
LotNumber = c.LotNumber,
FrameLaborStart = c.FrameLaborStart,
FrameLaborComplete = e.FrameLaborComplete,
Duration = (e.FrameLaborComplete - c.FrameLaborStart).Days
};
return framing.ToList();
}
}
}
Thanks to Andre, stuartd, and James R., I found out the solution was to use the EntityFramework DefaultIfEmpty().
var framing = from c in frameStart
join e in frameEnd on new { c.CustomerID, c.SubdivisionID, c.LotNumber } equals new { e.CustomerID, e.SubdivisionID, e.LotNumber } into jointable
from z in jointable.DefaultIfEmpty()
select new s84_Report_FrameLabor
{
CustomerID = c.CustomerID,
CustomerName = c.CustomerName,
SubdivisionID = c.SubdivisionID,
SubdivisionName = c.SubdivisionName,
LotNumber = c.LotNumber,
FrameLaborStart = c.FrameLaborStart,
FrameLaborComplete = z.FrameLaborComplete,
Duration = c.FrameLaborStart == null ? z.FrameLaborComplete == null ? (z.FrameLaborComplete - c.FrameLaborStart).Days : 0 : 0
};
return framing.ToList();

Categories