I'm writing a LINQ to SQL statement, and I'm after the standard syntax for a normal inner join with an ON clause in C#.
How do you represent the following in LINQ to SQL:
select DealerContact.*
from Dealer
inner join DealerContact on Dealer.DealerID = DealerContact.DealerID
It goes something like:
from t1 in db.Table1
join t2 in db.Table2 on t1.field equals t2.field
select new { t1.field2, t2.field3}
It would be nice to have sensible names and fields for your tables for a better example. :)
Update
I think for your query this might be more appropriate:
var dealercontacts = from contact in DealerContact
join dealer in Dealer on contact.DealerId equals dealer.ID
select contact;
Since you are looking for the contacts, not the dealers.
And because I prefer the expression chain syntax, here is how you do it with that:
var dealerContracts = DealerContact.Join(Dealer,
contact => contact.DealerId,
dealer => dealer.DealerId,
(contact, dealer) => contact);
To extend the expression chain syntax answer by Clever Human:
If you wanted to do things (like filter or select) on fields from both tables being joined together -- instead on just one of those two tables -- you could create a new object in the lambda expression of the final parameter to the Join method incorporating both of those tables, for example:
var dealerInfo = DealerContact.Join(Dealer,
dc => dc.DealerId,
d => d.DealerId,
(dc, d) => new { DealerContact = dc, Dealer = d })
.Where(dc_d => dc_d.Dealer.FirstName == "Glenn"
&& dc_d.DealerContact.City == "Chicago")
.Select(dc_d => new {
dc_d.Dealer.DealerID,
dc_d.Dealer.FirstName,
dc_d.Dealer.LastName,
dc_d.DealerContact.City,
dc_d.DealerContact.State });
The interesting part is the lambda expression in line 4 of that example:
(dc, d) => new { DealerContact = dc, Dealer = d }
...where we construct a new anonymous-type object which has as properties the DealerContact and Dealer records, along with all of their fields.
We can then use fields from those records as we filter and select the results, as demonstrated by the remainder of the example, which uses dc_d as a name for the anonymous object we built which has both the DealerContact and Dealer records as its properties.
var results = from c in db.Companies
join cn in db.Countries on c.CountryID equals cn.ID
join ct in db.Cities on c.CityID equals ct.ID
join sect in db.Sectors on c.SectorID equals sect.ID
where (c.CountryID == cn.ID) && (c.CityID == ct.ID) && (c.SectorID == company.SectorID) && (company.SectorID == sect.ID)
select new { country = cn.Name, city = ct.Name, c.ID, c.Name, c.Address1, c.Address2, c.Address3, c.CountryID, c.CityID, c.Region, c.PostCode, c.Telephone, c.Website, c.SectorID, Status = (ContactStatus)c.StatusID, sector = sect.Name };
return results.ToList();
You create a foreign key, and LINQ-to-SQL creates navigation properties for you. Each Dealer will then have a collection of DealerContacts which you can select, filter, and manipulate.
from contact in dealer.DealerContacts select contact
or
context.Dealers.Select(d => d.DealerContacts)
If you're not using navigation properties, you're missing out one of the main benefits on LINQ-to-SQL - the part that maps the object graph.
Use Linq Join operator:
var q = from d in Dealer
join dc in DealerConact on d.DealerID equals dc.DealerID
select dc;
basically LINQ join operator provides no benefit for SQL. I.e. the following query
var r = from dealer in db.Dealers
from contact in db.DealerContact
where dealer.DealerID == contact.DealerID
select dealerContact;
will result in INNER JOIN in SQL
join is useful for IEnumerable<> because it is more efficient:
from contact in db.DealerContact
clause would be re-executed for every dealer
But for IQueryable<> it is not the case. Also join is less flexible.
Actually, often it is better not to join, in linq that is. When there are navigation properties a very succinct way to write your linq statement is:
from dealer in db.Dealers
from contact in dealer.DealerContacts
select new { whatever you need from dealer or contact }
It translates to a where clause:
SELECT <columns>
FROM Dealer, DealerContact
WHERE Dealer.DealerID = DealerContact.DealerID
Inner join two tables in linq C#
var result = from q1 in table1
join q2 in table2
on q1.Customer_Id equals q2.Customer_Id
select new { q1.Name, q1.Mobile, q2.Purchase, q2.Dates }
Use LINQ joins to perform Inner Join.
var employeeInfo = from emp in db.Employees
join dept in db.Departments
on emp.Eid equals dept.Eid
select new
{
emp.Ename,
dept.Dname,
emp.Elocation
};
Try this :
var data =(from t1 in dataContext.Table1 join
t2 in dataContext.Table2 on
t1.field equals t2.field
orderby t1.Id select t1).ToList();
OperationDataContext odDataContext = new OperationDataContext();
var studentInfo = from student in odDataContext.STUDENTs
join course in odDataContext.COURSEs
on student.course_id equals course.course_id
select new { student.student_name, student.student_city, course.course_name, course.course_desc };
Where student and course tables have primary key and foreign key relationship
try instead this,
var dealer = from d in Dealer
join dc in DealerContact on d.DealerID equals dc.DealerID
select d;
var Data= (from dealer in Dealer join dealercontact in DealerContact on dealer.ID equals dealercontact.DealerID
select new{
dealer.Id,
dealercontact.ContactName
}).ToList();
var data=(from t in db.your tableName(t1)
join s in db.yourothertablename(t2) on t1.fieldname equals t2.feldname
(where condtion)).tolist();
var list = (from u in db.Users join c in db.Customers on u.CustomerId equals c.CustomerId where u.Username == username
select new {u.UserId, u.CustomerId, u.ClientId, u.RoleId, u.Username, u.Email, u.Password, u.Salt, u.Hint1, u.Hint2, u.Hint3, u.Locked, u.Active,c.ProfilePic}).First();
Write table names you want, and initialize the select to get the result of fields.
from d1 in DealerContrac join d2 in DealerContrac on d1.dealearid equals d2.dealerid select new {dealercontract.*}
One Best example
Table Names : TBL_Emp and TBL_Dep
var result = from emp in TBL_Emp join dep in TBL_Dep on emp.id=dep.id
select new
{
emp.Name;
emp.Address
dep.Department_Name
}
foreach(char item in result)
{ // to do}
Related
I have a SQL statement, that I want to implement in a .NET website project. I don't understand how to join in a particular field, as the fields aren't available when I just select from the table.
My SQL
SELECT *
FROM [vResidence] c
JOIN [vJobs] j on c.UID = j.UID
This is the LINQ I have tried, but I am stuck at the 'ON' part:
results = (from j in vJobs
join cr in vResidence on ??? )
When I try 'j.', the only option I get is 'equals'.
You can follow as this.connect to tables as JOIN use equals keyword
var result = from r in vResidence
join j vJobs on r.UID equals j.UID
select new {[yourcolnum]};
You can try this
var result = (from j in vJobs
join cr in vResidence
on j.UID equals cr.UID
select new {
...
}).ToList();
The Linq expression is the following:
from t1 in Table1
join t2 in Table2
on t1.ID equals t2.ID
The join clause on must be do in order: first the first table, then the second.
The keyword equals must be use.
Apart from the above Linq answers, we can do JOIN using Enumerable.Join extension with Lambda expressions. Try something like,
var result = vJobs.Join(vResidence, jb => new { jb.UID }, res => new { res.UID },
(jb, res) => new { jb, res })
.Select(x => x.jb) //Select the required properties (from both objects) with anonymous object or select left/right object
.ToList();
C# Fiddle with sample data.
I have a problem. I get all data in var type variable and then want to apply a join with database table in code first approach. Facing problem, lot of search on internet and apply but failed.
var joinedData =
from menuGroup in _menuGroupMenusRepository.GetAll()
.Where(x => x.GroupId == input.GroupId)
join menus in _menuRepository.GetAll()
on menuGroup.MenuId equals menus.Id
join categSubcateg in _menuCategSubCategRepository.GetAll()
on menus.Id equals categSubcateg.MenuId
join categ in _menuCategoryRepository.GetAll()
on categSubcateg.CategoryId equals categ.Id
select new
{
CategoryId = categSubcateg.CategoryId,
CategoryName = categ.Category,
};
Now I want joinedData variable join with MainMenuSort table.
MainMenuSort table also have groupid and categoryid.
to perform join you just need to do as below
var q=(from jd in joinedData
join mms in dataContext.MainMenuSort
on jd.CategoryId equals mms.CategoryId
select jd).ToList();
if its datatable then
var q=(from jd in joinedData
join mms in dtMainMenuSort.AsEnumerable()
on jd.CategoryId equals mms.Field<int>("CategoryId")
select jd).ToList();
I am trying to perform an outer join in C# using Linq, the person mentoring me keeps saying I shouldn't try to do an outer join which isn't really an answer.
What I got from the other threads is that I need the .DefaultIfEmpty() where ever I may not have a record.
I tried it first on just the lines where there may be a missing information then added it to every line just to see if that was the problem.
Every time I run this I get only the inner join records. It works great other than it is not including the two records from my DB that only have information in the first two tables.
var sqlQuery =
from s in ctx.Suppliers
from sp in ctx.SupplierParts
.Where(sp => sp.SupplierID == s.SupplierID)
.DefaultIfEmpty()
from sm in ctx.SupplierManufacturerRelations
.Where(sm => sm.SupplierPNID == sp.SupplierPNID)
.DefaultIfEmpty()
from mp in ctx.ManufacturerParts
.Where(mp => mp.MfgPNID.Equals(sm.MfgPNID))
.DefaultIfEmpty()
from m in ctx.Manufacturers
.Where(m => m.ManufacturerID.Equals(mp.ManufacturerID))
.DefaultIfEmpty()
from im in ctx.ItemMasters
.Where(im => im.PreID == mp.PreID)
.Where(im => im.PartNumber == mp.PartNumber)
.DefaultIfEmpty()
from c in ctx.ComponentClasses
.Where(c => c.CCID == im.CCID)
.DefaultIfEmpty()
from um in ctx.UnitsOfMeasures
.Where(um => um.UOMID == sp.UOMID)
.DefaultIfEmpty()
select new
{ my variables}
var querylist = sqlQuery.Where(n => n.SupplierID == thisSupplier).ToList();
I also tried
from s in ctx.Suppliers
join sp in ctx.SupplierParts on s.SupplierID equals sp.SupplierID
join sm in ctx.SupplierManufacturerRelations on sp.SupplierPNID equals sm.SupplierPNID into spartgroup
from sm in spartgroup.DefaultIfEmpty()
join mp in ctx.ManufacturerParts on sm.MfgPNID equals mp.MfgPNID into mpartgroup
from mp in mpartgroup.DefaultIfEmpty()
join m in ctx.Manufacturers on mp.ManufacturerID equals m.ManufacturerID into mgroup
from m in mgroup.DefaultIfEmpty()
join im in ctx.ItemMasters
on new { key1 = (int)mp.PreID, key2 = (int)mp.PartNumber }
equals new { key1 = im.PreID, key2 = im.PartNumber }
into tpartgroup
from im in tpartgroup.DefaultIfEmpty()
join c in ctx.ComponentClasses on im.CCID equals c.CCID into fullgroup
from c in fullgroup.DefaultIfEmpty()
join um in ctx.UnitsOfMeasures on sp.UOMID equals um.UOMID
This SQL query works and doesn't omit the rows
SELECT Supplier.SupplierID
, SupplierPart.SupplierPNID
, SupplierPart.SupplierPN
, SupplierPart.Description
, SupplierManufacturerRelation.MfgPNID
, ManufacturerPart.PreID
, ManufacturerPart.PartNumber
, ItemMaster.CCID
, ItemMaster.Description AS Expr1
FROM Supplier
Inner JOIN SupplierPart
ON Supplier.SupplierID = SupplierPart.SupplierID
Left JOIN SupplierManufacturerRelation
ON SupplierPart.SupplierPNID = SupplierManufacturerRelation.SupplierPNID
Left JOIN ManufacturerPart
ON SupplierManufacturerRelation.MfgPNID = ManufacturerPart.MfgPNID
Left JOIN ItemMaster
ON ManufacturerPart.PreID = ItemMaster.PreID
AND ManufacturerPart.PartNumber = ItemMaster.PartNumber
WHERE Supplier.SupplierID = 9
For translating SQL to LINQ query comprehension:
Translate FROM subselects as separately declared variables.
Translate each clause in LINQ clause order, translating monadic operators (DISTINCT, TOP, etc) into functions applied to the whole LINQ query.
Use table aliases as range variables. Use column aliases as anonymous type field names.
Use anonymous types (new { ... }) for multiple columns.
Left Join is simulated by using a into join_variable and doing another from from the join variable followed by .DefaultIfEmpty().
Replace COALESCE with the conditional operator and a null test.
Translate IN to .Contains() and NOT IN to !...Contains()
SELECT * must be replaced with select range_variable or for joins, an anonymous object containing all the range variables.
SELECT fields must be replaced with select new { ... } creating an anonymous object with all the desired fields or expressions.
Proper FULL OUTER JOIN must be handled with an extension method.
So from your SQL, your query should look like:
var ans = from s in ctx.Suppliers
join sp in ctx.SupplierParts on s.SupplierID equals sp.SupplierID
join sm in ctx.SupplierManufacturerRelations on sp.SupplierPNID equals sm.SupplierPNID into smj
from sm in smj.DefaultIfEmpty()
join mp in ctx.ManufacturerParts on sm?.MfgPNID equals mp.MfgPNID into mpj
from mp in mpj.DefaultIfEmpty()
join im in ctx.ItemMasters on new { key1 = (int)mp.PreID, key2 = (int)mp.PartNumber } equals new { key1 = im.PreID, key2 = im.PartNumber } into imj
from im in imj.DefaultIfEmpty()
select new {
s.SupplierID, sp.SupplierPNID, sp.SupplierPN, sp.Description, sm.MfgPNID, mp.PreID, mp.PartNumber, im.CCID, Expr1 = im.Description
};
I am trying to move from simple SQL to EF.
But there are some complex queries(joins) that it seems to hard to generate the linq for.
At first I tried to use sqltolinq tool to generate the linq but it gives error as some of the things are not supported in the query.
here is the linq:
var entryPoint = (from ep in dbContext.tbl_EntryPoint
join e in dbContext.tbl_Entry on ep.EID equals e.EID
join t in dbContext.tbl_Title on e.TID equals t.TID
where e.OwnerID == user.UID
select new {
UID = e.OwnerID,
TID = e.TID,
Title = t.Title,
EID = e.EID
});
The table entry has many entries that I would like to group and get the latest for each group. But then I would need to select into a view model object which will be bind to gridview.
I dont know where I can implement the logic to group by and get the latest from each and be able to get values from join table into viewModel object.
somewhere I need to add
group entry by new
{
entry.aID,
entry.bCode,
entry.Date,
entry.FCode
}
into groups
select groups.OrderByDescending(p => p.ID).First()
in the above linq to retrieve latest from each group.
You can insert group by right after the joins:
var query =
from ep in dbContext.tbl_EntryPoint
join e in dbContext.tbl_Entry on ep.EID equals e.EID
join t in dbContext.tbl_Title on e.TID equals t.TID
where e.OwnerID == user.UID
group new { ep, e, t } by new { e.aID, e.bCode, e.Date, e.FCode } into g
let r = g.OrderByDescending(x => x.e.ID).FirstOrDefault()
select new
{
UID = r.e.OwnerID,
TID = r.e.TID,
Title = r.t.Title,
EID = r.e.EID
};
The trick here is to include what you need after the grouping between group and by.
However, the above will be translated to CROSS APPLY with all joins included twice. If the grouping key contains fields from just one table, it could be better to perform the grouping/selecting the last grouping element first, and then join the result with the rest:
var query =
from e in (from e in dbContext.tbl_Entry
where e.OwnerID == user.UID
group e by new { e.aID, e.bCode, e.Date, e.FCode } into g
select g.OrderByDescending(e => e.ID).FirstOrDefault())
join ep in dbContext.tbl_EntryPoint on e.EID equals ep.EID
join t in dbContext.tbl_Title on e.TID equals t.TID
select new
{
UID = e.OwnerID,
TID = e.TID,
Title = t.Title,
EID = e.EID
};
Please anyone can help me to write this sql query into Linq. i have tried..
this is my sql query
select o.OrderID,o.Nature,o.Date,od.TotalPrice,os.OrderStatus,lo.FirstName,lo.EmailAddress,lo.PhoneNumber
from [dbo].[Order] o
inner join [dbo].[tbl_OrderDetails] od on od.OrderID = o.OrderID
inner join [dbo].[tbl_OrderHistory] oh on oh.OrderID = o.OrderID
inner join [dbo].[tbl_Login] lo on o.UserID = lo.UserID
inner join dbo.tbl_OrderStatus os on oh.OrderStatusID= os.OrderStatusID
group by o.OrderID,o.Nature,od.TotalPrice,o.Date,os.OrderStatus,lo.FirstName,lo.EmailAddress,lo.PhoneNumber
and this is my try
public override orderDetailModel orderDetails(int id)
{
var results = from o in obj.Orders
join od in obj.tbl_OrderDetails on o.OrderID equals od.OrderID
join oh in obj.tbl_OrderHistory on o.OrderID equals oh.OrderID
join l in obj.tbl_Login on o.UserID equals l.UserID
join os in obj.tbl_OrderStatus on oh.OrderStatusID equals os.OrderStatusID
where (od.OrderID == id)
group o by new { o.Nature, o.OrderID } into
select new orderDetailModel
{
OrderID = o.OrderID,
OrderStatus = os.OrderStatus,
Date = o.Date,
DeliveryNature = o.Nature,
EmailAddress = l.EmailAddress,
FirstName = l.FirstName,
PhoneNumber = l.PhoneNumber,
TotalPrice = od.TotalPrice
};
//group o by new {o.OrderID};
orderDetailModel data = (orderDetailModel)results.FirstOrDefault();
return data;
}
but this is wrong query its not working fine please help me
You need to correct the group by clause, like you have in the SQL query like this:-
group new { o, l } by new { o.OrderID,o.Nature,od.TotalPrice,o.Date,os.OrderStatus,
l.FirstName, l.EmailAddress,l.PhoneNumber } into g
select new orderDetailModel
{
OrderID = g.Key.OrderID,
OrderStatus = g.Key.OrderStatus,
Date = g.Key.Date,
..and so on
};
Since you need the grouping on two tables Order & tbl_Login you will have to first project them as anonymous type group new { o, l } then specify all the groupings and finally while projecting use Key to get the respective items.
I guess that actually, also the SQL query is not correct.
I would simply use a SELECT DISTINCT ... instead of Grouping all the columns.
Anyway, first thing to do:
Check if databases is designed correctly. As far as i can see, if you're joining the table with their Ids, i don't understand why you need to group all the data. If you have duplicates, maybe the error is in the Database design.
If you can't change your Database, or you are happy with it, then use the following LINQ approach:
var distinctKeys = allOrderDetails.Select(o => new { o.OrderID, o.Nature, o.TotalPrice, o.Date,o.OrderStatus,o.FirstName, o.EmailAddress,o.PhoneNumber }).Distinct();
var joined = from e in allOrderDetails
join d in distinctKeys
on new { o.OrderID, o.Nature,o.TotalPrice, o.Date,o.OrderStatus, o.FirstName, o.EmailAddress, o.PhoneNumber } equals d select e;
joined.ToList(); // gives you the distinct/grouped list