LINQ-to-SQL Joins - linq

I have a table called Payroll. Payroll can have many PayStubs. In other words there is table called PayStub that is a child entity of Payroll. PayStub has a child Entity called PayrollTax. I want to write a LINQ-to-SQL query that gets all payrolls which have more than one Payroll Tax. I use the following query:
public IList<Payroll> GetPayrollsWithPayrollTaxes()
{
return (from payroll in ActiveContext.Payrolls
join payStub in ActiveContext.PayStubs on payroll.PayrollID equals payStub.PayrollID
where payStub.InternalPayrollTaxes.Count > 0
select payroll
).ToList();
}
The problem is since there is a one to many relationship between Payroll and PayStub, I end up getting the same Payroll twice. I want a unique list of Payrolls.
Any ideas and suggestions are appreciated!

I think using Any (EXISTS in SQL) might help you here.
public IList<Payroll> GetPayrollsWithPayrollTaxes()
{
return (from payroll in ActiveContext.Payrolls
where ActiveContextPayStubs.Any(payStub =>
payroll.PayrollID == payStub.PayrollID &&
payStub.InternalPayrollTaxes.Any())
select payroll
).ToList();
}

Have you tried .Distinct().ToList() ?
Or you could add an into after the join like this:
(from payroll in ActiveContext.Payrolls
join payStub in ActiveContext.PayStubs on payroll.PayrollID equals payStub.PayrollID into payStubGroup
where payStubGroup.Any(p => p.InternalPayrollTaxes.Any())
select payroll
).ToList();

Related

linq query with many-to-many relationship

Let’s assume I have three tables in my database:
Authors(PK Id, AuthorName)
Books(PK Id, BookName)
Authors_Books(FK BookId, FK AuthorId)
I need to write a method which passes in a parameter int[] authorsIds and returns all books (Id, BookName, list of authors of this book) if it was written by any author whose Id contains in int[] authorsIds parameter.
I need LINQ query (query method).
I really need a help. Appreciate your help very much.
var int[] authors = { 1, 2, 3 };
var books = from book in books
where book.Authors.Any(x => authors.Contains(x.AuthorId))
select book;
PS: I assume book.Authors is your reference to Authors_Books table (or maybe has a different name).
this answer is based on the exact structure without considering that A obj has B in its structure
var book = from b in books
where book.Id in ( from ab in AuthersBooks
where selectedAuthers.contains(ab.AutherId)
select ab.bookId ) //now we have books that are authered by one of the selected authers
select new { BookId = b.Id, // now we create an anonymos object to contain any info we need
BookName = b.Name,
BookAuthers = (from a in authers
join ab in AuthersBooks
on a.Id == ab.AuthersId
where ab.bookid == b.Id
select a)
this will propably have syntax errors and after correcting you may get an error about multiple threads which already has an answer here

Composite group join

I want to do a group join with the following three tables using linq extension methods
Custumer
Order
OrderShippingInfo
Custumer can have many Orders and each order can have only one OrderShippingInfo.
So my goal is do a group join of these 3 tables and return a anonymous object that has one Customer and an array of {Order, OrderShippinfo}.
I know how to do a groupjoin between customer and order but I don't know how to add the OrderShippInfo in the collection
Customer.GroupJoin(Order, c=>c.customerID, o=>o.CustomerID, (c,o)=> new {c,o})
Thanks a lot
How about that:
Customer.GroupJoin(Order.Join(OrderShippinInfo,
o=>o.OrderID,
s=>s.OrderID,
(o, s) => new { Order = o, ShippingInfo = s}),
c=>c.customerID,
oi=>oi.Order.CustomerID,
(c,oi)=> new {c,oi})

Nested Query or Sub query linq

I have two classes. Bills and Transactions. One bill is made up of many transactions. I am able to display bills and I am able to display transactions on their own. But I would like to display the last 10 bills (this part is done), but each bill should show all its transactions.
This part of the code is used to get all transactions of a bill
{ Bill bill = (Bill)Bills.Instance.GetBillsByCustomerID(id);
//get all transactions of bill
var transactions = from t in this._entities.Transactions
where t.Bill.bID == bill.bID
select new
{
t.Product.pName, t.tQty, t.tUnitPrice, t.Bill.bTotal, t.Bill.bTimestamp, t.Bill.bCustomerIDF
};
}
Now I would like that the following query below, would have some sort of nested query where all transactions OF EACH BILL are obtained: (at the moment, this only displays 10 bills - and no transactions
{
//returns top 10
var bills = (from b in this._entities.Bills
where b.bCustomerIDF == id
orderby b.bTimestamp descending
select new { b.bTotal, b.bTimestamp, b.Customer.cName}).Take(10);
return bills;
}
Can you please guide me to a simple solution? Thank you
I believe you want a join with an into
var bills = (from b in this._entities.Bills
join t in this._entities.Transactions on t.Bill.bID equals b.bID into tg
where b.bCustomerIDF == id
orderby b.bTimestamp descending
select new
{
b.bTotal,
b.bTimestamp,
b.Customer.cName,
Transactions = tg
}
).Take(10);
return bills;
I would have thought that you should just be able to add something like the following into your select:
transactions.Where(x=>x.Bill.bID == b.bID)`
That having been said I do also think it sounds like your object model is wrong. I'd have expected a Bill to have a collection of Transactions that are on that Bill.

Combining LINQ queries to get unique records

I'm trying to figure out a way of combining these 2 LINQ queries. The first one creates a list of holiday customers and the second one de-dupes the list based on the email address.
Whats the most succinct way of combining them?
var allNonBuyers = (from a in allCustomers
where !(from q in db.Quotes
where q.CreationDate > DateTime.Now.AddMinutes(duration)
join p in db.Passengers on q.QuoteGUID equals p.QuoteGUID
where q.PolicyNumber != null
select p.EmailAddress).Contains(a.EmailAddress)
select new { a.QuoteGUID, a.Title, a.FirstName, a.LastName, a.EmailAddress, a.Telephone });
var distinctNonBuyers = from buyer in allNonBuyers
group buyer by buyer.EmailAddress
into gbuyer
select gbuyer.First();
You normally don't need to - because LINQ has delayed execution, when you ask for the result it will all be combined. If this is Linq-To-Sql then it will be executed as one statement (if possible) against the database.

ef and linq extension method

I have this sql that i want to have written in linq extension method returning an entity from my edm:
SELECT p.[Id],p.[Firstname],p.[Lastname],prt.[AddressId],prt.[Street],prt.[City]
FROM [Person] p
CROSS APPLY (
SELECT TOP(1) pa.[AddressId],a.[ValidFrom],a.[Street],a.[City]
FROM [Person_Addresses] pa
LEFT OUTER JOIN [Addresses] AS a
ON a.[Id] = pa.[AddressId]
WHERE p.[Id] = pa.[PersonId]
ORDER BY a.[ValidFrom] DESC ) prt
Also could this be re-written in linq extension method using 3 joins?
Assuming you have set the Person_Addresses table up as a pure relation table (i.e., with no data besides the foreign keys) this should do the trick:
var persons = model.People
.Select(p => new { p = p, a = p.Addresses.OrderByDescending(a=>a.ValidFrom).First() })
.Select(p => new { p.p.Id, p.p.Firstname, p.p.LastName, AddressId = p.a.Id, p.a.Street, p.a.City });
The first Select() orders the addresses and picks the latest one, and the second one returns an anonymous type with the properties specified in your query.
If you have more data in your relation table you're gonna have to use joins but this way you're free from them. In my opinion, this is more easy to read.
NOTE: You might get an exception if any entry in Persons have no addresses connected to them, although I haven't tried it out.

Resources