Entity Framework Join 3 Tables - c#

I'm trying to join three tables but I can't understand the method...
I completed join 2 tables
var entryPoint = dbContext.tbl_EntryPoint
.Join(dbContext.tbl_Entry,
c => c.EID,
cm => cm.EID,
(c, cm) => new
{
UID = cm.OwnerUID,
TID = cm.TID,
EID = c.EID,
}).
Where(a => a.UID == user.UID).Take(10);
I would like to include tbl_Title table with TID PK and get Title field.
Thanks a lot

I think it will be easier using syntax-based query:
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
}).Take(10);
And you should probably add orderby clause, to make sure Top(10) returns correct top ten items.

This is untested, but I believe the syntax should work for a lambda query. As you join more tables with this syntax you have to drill further down into the new objects to reach the values you want to manipulate.
var fullEntries = dbContext.tbl_EntryPoint
.Join(
dbContext.tbl_Entry,
entryPoint => entryPoint.EID,
entry => entry.EID,
(entryPoint, entry) => new { entryPoint, entry }
)
.Join(
dbContext.tbl_Title,
combinedEntry => combinedEntry.entry.TID,
title => title.TID,
(combinedEntry, title) => new
{
UID = combinedEntry.entry.OwnerUID,
TID = combinedEntry.entry.TID,
EID = combinedEntry.entryPoint.EID,
Title = title.Title
}
)
.Where(fullEntry => fullEntry.UID == user.UID)
.Take(10);

Related

Join where lambda query in EF Core 3.1

I have a problem to write in lambda query this sql query:
select c.Id, c.Name, c.SomeNumber, count(*) from TableA a
inner join TableB b
on a.Id = b.aId
inner join TableC c
on c.BId = b.Id
where b.Status = N'Approved'
and c.Scope = N'Scope1'
group by a.Id, a.Name, a.SomeNumber
Can you guys help me with this one ? I want to write lambda query to execute this in code. I'm using EF Core 3.1
This is what I ended up so far:
var query = await _dbContext.TableA.Where(a => a.TableB.Any(b => b.Status.Equals("Approved")
&& b.TableC.Any(c => c.Scope.Equals("Scope1"))))
.GroupBy(g => new { Id = g.Id, Name = g.Name, SomeNumber = g.SomeNumber })
.Select(s => new { Id = s.Key.Id, Name = s.Key.Name, SomeNumber = s.Key.SomeNumber, Count = s.Count() })
.GroupBy(g => g.Id).Select(s => new {Id = s.Key, Count = s.Count()}).ToListAsync();
Well, this is corrected query. I have used Query syntax which is more readable when query has lot of joins or SelectMany.
var query =
from a in _dbContext.TableA
from b in a.TableB
from c in b.TableC
where b.Status == "Approved" && c.Scope == "Scope1"
group a by new { a.Id, a.Name, a.SomeNumber } into g
select new
{
g.Key.Id,
g.Key.Name,
g.Key.SomeNumber,
Count = g.Count()
}
var result = await query.ToListAsync();
It's maybe easier to start from the many end and work up through the navigation properties
tableC
.Where(c => c.Scope == "Scope1" && c.BEntity.Status == "Approved")
.GroupBy(c => new
{
c.BEntity.AEntity.Id,
c.BEntity.AEntity.Name,
c.BEntity.AEntity.SomeNumber
})
.Select(g => new { g.Key.Id, g.Key.Name, g.Key.SomeNumber, Ct = g.Count()})
EF knows how to do joins when you navigate around the object tree in the where. By starting at the many and and working up to the 1 end of the relationship it means you don't have to get complex with asking "do any of the children of this parent have a status of ..."

Can't find the foreign key using Join for method syntax

I have these two tables: Category (Parent) and Product (Children).
I could use inner join with LINQ query syntax. But with method syntax, I could not get. p. doesn't load CategoryID
var db = new NorthwindEntities();
var cats = db.Categories;
var prods = db.Products;
var catProducts1 = from c in db.Categories
join p in db.Products
on c.CategoryID equals p.CategoryID
select new { c.CategoryName, p.ProductName };
var catProducts2 = db.Categories
.Join(db.Products, c=>c.CategoryID,p=>p);
Below is the correct syntax of Join lamda syntax for your scenario:
var catProducts2 = db.Categories.Join(db.Products,
c => c.CategoryId,
p => p.CategoryID,
(c, p) => new { c.CategoryName, p.ProductName })
.Select(s => new { s.CategoryName, s.ProductName });
You can check the usage of above query at fiddle -- https://dotnetfiddle.net/C3N2I2

How To Join Many Tables In Linq Lambda Expressions?

I Got This Lambda Expression But Does Not Work Correctly.Does Not Return Any Thing.Would You Help me Please on this:
var query = db.Cheque
.Join(db.Contracts,
C => C.ContractIDRef,
Con => Con.ContractID,
(C, Con) => new { Cheques1 = C, Contracts1 = Con })
.Join(db.Parties,
Con => Con.Contracts1.ContractID,
Pt => Pt.ContractIDRef,
(Con, Pt) => new { Contract2 = Con, Parites1 = Pt })
.Join(db.Persons,
Pt => Pt.Parites1.PartyIDRef,
P => P.PersonID,
(Pt, P) => new { Parites2 = Pt, Persons1 = P })
.Join(db.Company,
Pt => Pt.Parites2.Parites1.CompanyIDRef,
Com => Com.CompanyID,
(Pt, Com) => new { Parites3 = Pt, Company1 = Com })
.Join(db.Bank,
C => C.Parites3.Parites2.Contract2.Cheques1.BankIDRef,
B => B.BankID,
(C, B) => new { Cheque2 = C, Bank1 = B })
.Join(db.Flats,
Con => Con.Cheque2.Parites3.Parites2.Contract2.Contracts1.FlatIDRef,
F => F.FlatID,
(Con, F) => new { Contract3 = Con, Flat1 = F })
.Join(db.Projects,
F => F.Flat1.ProjectIDRef,
Pr => Pr.ProjectID,
(F, Pr) =>
new
{
ChequeNumber = F.Contract3.Cheque2.Parites3.Parites2.Contract2.Cheques1.ChequeNo,
ChequeIDRef = F.Contract3.Cheque2.Parites3.Parites2.Contract2.Cheques1.ChequeIDRef,
ChequePrice = F.Contract3.Cheque2.Parites3.Parites2.Contract2.Cheques1.Amount,
BankName = F.Contract3.Bank1.BankName,
BranchName = F.Contract3.Cheque2.Parites3.Parites2.Contract2.Cheques1.BranchName,
ChequeDate = F.Contract3.Cheque2.Parites3.Parites2.Contract2.Cheques1.ChequeDate,
AccountNumber = F.Contract3.Cheque2.Parites3.Parites2.Contract2.Cheques1.AccNo,
AccountOwner = F.Contract3.Cheque2.Parites3.Parites2.Contract2.Cheques1.ChequeOwnerName,
}
)
`.Where(Total => SelectedChequesList.Contains(Total.ChequeIDRef.Value)).ToList();
I will start with converting the above to the query syntax. While I'm a fan of the method syntax, using it in a complex queries involving multiple joins is a real pain. I needed a lot of time to read and try to follow the above query, so let do that:
var query =
from cheque in db.Cheque
join contract in db.Contracts on cheque.ContractIDRef equals contract.ContractID
join party in db.Parties on contract.ContractID equals party.ContractIDRef
join person in db.Persons on party.PartyIDRef equals person.PersonID
join company in db.Companies on party.CompanyIDRef equals company.CompanyID
join bank in db.Bank on cheque.BankIDRef equals bank.BankID
join flat in db.Flats on contract.FlatIDRef equals flat.FlatID
join project in db.Projects on flat.ProjectIDRef equals project.ProjectID
where SelectedChequesList.Contains(cheque.ChequeIDRef.Value)
select new
{
ChequeNumber = cheque.ChequeNo,
ChequeIDRef = cheque.ChequeIDRef,
ChequePrice = cheque.Amount,
BankName = bank.BankName,
BranchName = cheque.BranchName,
ChequeDate = cheque.ChequeDate,
AccountNumber = cheque.AccNo,
AccountOwner = cheque.ChequeOwnerName,
};
Now, one thing that can be seen is that most of the joins are not used. But let assume they are needed for some reason. Note that all the joins are INNER joins, so any of them can cause the query to return empty result if there is no matching record.
The problem is most probably in this join
join person in db.Persons on party.PartyIDRef equals person.PersonID
Instead of PartyIDRef I guess it should be something like PersonIDRef.

Linq query with Contains having null value

var qry = from _Cr in _er.Courses
from _R in _er.ResultsHeaders
where _R.Studentid == studentid
&& !_Cr.CourseID.Contains( _R.CourseID )
select new Obj_getCourses
{
Courseid = _Cr.CourseID,
CourseName = _Cr.CourseName
};
_er.CoursesTable have 4 values in it and _er.ResultsHeader table is empty. I was expecting 4 values from query but the query is not returning any Value. This is the query I am trying to write in LINQ.
Select * \
from Courses \
where courseid not in (Select courseid from ResultsHeader where studentid = 123);
Help require.
Thanks in advance
This should give you your desired results. I have written it in C# statement style so hopefully that having it is LINQ style was not a pre-requisite...
var qry = _er.Courses
.Where( c => !c.CourseID.Contains(_er.ResultsHeader
.Where( r => r.StudentID == 123)
.Select(r => r.CourseID)
)
.Select(c => new Obj_getCourses
{
Courseid = c.CourseID,
Coursename = c.CourseName
});
To get SQL you posted, you should try following query:
var qry = from _Cr in _er.Courses
where !_er.ResultsHeader.Where(r => r.StudentId == studentId)
.Select(r => r.CourseID)
.Contains(_Cr.CourseID)
select new Obj_getCourses
{
Courseid = _Cr.CourseID,
CourseName = _Cr.CourseName
};

Linq to select data from one table not in other table

Hi i have the following code to select data from one table not in other table
var result1 = (from e in db.Users
select e).ToList();
var result2 = (from e in db.Fi
select e).ToList();
List<string> listString = (from e in result1
where !(from m in result2
select m.UserID).Contains(e.UserID)
select e.UserName).ToList();
ViewBag.ddlUserId = listString;
Am getting value inside listString .But got error while adding listString to viewbag.
Unable to cast object of type 'System.Collections.Generic.List`1[System.String]' to type 'System.Collections.Generic.IEnumerable`1[Main.Models.Admin.User]'.
First, could you update your question with the entire method so that we can see what might be going on with the ViewBag? Because your code should work just fine, assigning whatever value to the ViewBag is no problem normally:
ViewBag.property1 = 0;
ViewBag.property1 = "zero";
works just fine. ViewBag is dynamic. Now, you could get that error if you would later try to assing ViewBag.ddlUserId to something that actually is the wrong type.
I would like you to rewrite your statement as well, let me explain why. Assume for a moment that you have a lot ( > 100.000) of User records in your db.Users and we assume the same for Fi as well. In your code, result1 and result2 are now two lists, one containing >100.000 User objects and the other >100.000 Fi objects. Then these two lists are compared to each other to produce a list of strings. Now imagine the resource required for your web server to process this. Under the assumption that your actually using/accessing a separate SQL server to retrieve your data from, it would be a lot better and faster to let that server do the work, i.e. producing the list of UserID's.
For that you'd either use Kirill Bestemyanov's answer or the following:
var list = (from user in db.Users
where !db.Fi.Any(f => f.UserID == user.UserID)
select user.UserName).ToList()
This will produce just one query for the SQL server to execute:
SELECT
[Extent1].[UserName] AS [UserName]
FROM [dbo].[Users] AS [Extent1]
WHERE NOT EXISTS (SELECT
1 AS [C1]
FROM [dbo].[Fi] AS [Extent2]
WHERE [Extent2].[UserID] = [Extent1].[UserID]
)}
which in the end is what you want...
Just to clarify more:
var list = (from user in db.Users
where !db.Fi.Any(f => f.UserID == user.UserID)
select user.UserName).ToList()
can be written as the following lambda expression as well:
var list = db.Users.Where(user => !db.Fi.Any(f => f.UserID == user.UserID))
.Select(user => user.UserName).ToList()
which from the looks of it is slightly different from Kirill Bestemyanov's answer (which I slightly modified, just to make it look more similar):
var list = db.Users.Where(user => !db.Fi.Select(f => f.UserID)
.Contains(user.UserID))
.Select(user => user.UserName).ToList();
But, they will in fact produce the same SQL Statement, thus the same list.
I will rewrite it to linq extension methods:
List<string> listString = db.Users.Where(e=>!db.Fi.Select(m=>m.UserID)
.Contains(e.UserID))
.Select(e=>e.UserName).ToList();
try it, it should work.
Try this it is very simple.
var result=(from e in db.Users
select e.UserID).Except(from m in db.Fi
select m.UserID).ToList();
var res = db.tbl_Ware.where(a => a.tbl_Buy.Where(c => c.tbl_Ware.Title.Contains(mtrTxtWareTitle.Text)).Select(b => b.Ware_ID).Contains(a.ID));
This mean in T-SQL is:
SELECT * FROM tbl_Ware WHERE id IN (SELECT ware_ID, tbl_Buy WHErE tbl_Ware.title LIKE '% mtrTxtwareTitle.Text %')
getdata = (from obj in db.TblManageBranches
join objcountr in db.TblManageCountries on obj.Country equals objcountr.iCountryId.ToString() into objcount
from objcountry in objcount.DefaultIfEmpty()
where obj.IsActive == true
select new BranchDetails
{
iBranchId = obj.iBranchId,
vBranchName = obj.vBranchName,
Addressline1 = obj.Addressline1,
Adminemailid = obj.Adminemailid,
BranchType = obj.BranchType,
Country = objcountry.vCountryName,
CreatedBy = obj.CreatedBy,
CreatedDate = obj.CreatedDate,
iArea = obj.iArea,
iCity = obj.iCity,
Infoemailid = obj.Infoemailid,
Landlineno = obj.Landlineno,
Mobileno = obj.Mobileno,
iState = obj.iState,
Pincode = obj.Pincode,
Processemailid = obj.Processemailid,
objbranchbankdetails = (from objb in db.TblBranchesBankDetails.Where(x => x.IsActive == true && x.iBranchId == obj.iBranchId)
select new ManageBranchBankDetails
{
iBranchId = objb.iBranchId,
iAccountName = objb.iAccountName,
iAccountNo = objb.iAccountNo,
iBankName = objb.iBankName,
iAccountType = objb.iAccountType,
IFSCCode = objb.IFSCCode,
SWIFTCode = objb.SWIFTCode,
CreatedDate = objb.CreatedDate,
Id = objb.Id
}).FirstOrDefault(),
objbranchcontactperson = (from objc in db.tblbranchcontactpersons.Where(x => x.Isactive == true && x.branchid == obj.iBranchId)
select new ManageBranchContactPerson
{
branchid = objc.branchid,
createdate = objc.createdate,
Id = objc.Id,
iemailid = objc.iemailid,
ifirstname = objc.ifirstname,
ilandlineno = objc.ilandlineno,
ilastname = objc.ilastname,
imobileno = objc.imobileno,
title = objc.title,
updateddate=objc.updateddate,
}).ToList(),
}).OrderByDescending(x => x.iBranchId).ToList();
getdata = (from obj in db.TblManageBranches join objcountr in db.TblManageCountries on obj.Country equals objcountr.iCountryId.ToString() into objcount from objcountry in objcount.DefaultIfEmpty() where obj.IsActive == true
select new BranchDetails
{
iBranchId = obj.iBranchId,
vBranchName = obj.vBranchName,
objbranchbankdetails = (from objb in db.TblBranchesBankDetails.Where(x => x.IsActive == true && x.iBranchId == obj.iBranchId)
select new ManageBranchBankDetails
{
iBranchId = objb.iBranchId,
iAccountName = objb.iAccountName,
}).FirstOrDefault(),
objbranchcontactperson = (from objc in db.tblbranchcontactpersons.Where(x => x.Isactive == true && x.branchid == obj.iBranchId)
select new ManageBranchContactPerson
{
branchid = objc.branchid,
createdate = objc.createdate,
Id = objc.Id,
iemailid = objc.iemailid,
}).ToList(),
}).OrderByDescending(x => x.iBranchId).ToList();

Categories