Writing the LINQ equaivalent of a SQL join - c#

This is the SQL query I have written:
select * from Addresses a
join ProviderAddresses pa on a.address_k = pa.address_k
where pa.provider_k = 'ABC123'
and pa.active = 1
and a.active = 1
and pa.addresstype_rtk = 'HOME'
And this is the LINQ query I wrote for it:
public IQueryable<Addresses> GetAddressesesForProvider(string provider_k, string addresstype_rtk)
{
var query = from a in this.Context.Addresses
join pa in this.Context.ProviderAddresses on a.Address_K equals pa.Address_K
where pa.AddressType_RTK == addresstype_rtk
&& pa.Active == true
&& a.Active == true
select a;
return query;
}
But it is wrong. The LINQ one return thousands of records and the SQL one returns only one record.
It is IQueryable because later I need to go through its results with a for-each loop.
In the SQL I am passing hard coded values for testing but in my code for me LINQ method I also pass the same hard coded values so that is not the issue.

Looks like you may have just missed adding the provider_k condition to the where;
public IQueryable<Addresses> GetAddressesesForProvider(string provider_k, string addresstype_rtk)
{
var query = from a in this.Context.Addresses
join pa in this.Context.ProviderAddresses on a.Address_K equals pa.Address_K
where pa.Provider_K == provider_k &&
pa.AddressType_RTK == addresstype_rtk &&
pa.Active == true &&
a.Active == true
select a;
return query;
}

Related

Filtering a IQueryable with results from another table

I have an EF query which gets products from the database.
var query = (from pPrice in db.ProductPricing
join prod in db.Products on pPrice.ProductID equals prod.ProductID
join productExt in db.ProductsExt on prod.ProductID equals productExt.ProductID into pExts
from prodExt in pExts.DefaultIfEmpty()
where (includeNonPublic || pPrice.ShowOnline == 1)
&& ((eventID.HasValue && pPrice.EventID == eventID) || (!eventID.HasValue && !pPrice.EventID.HasValue))
orderby prod.DisplayOrder
select new ProductPricingInfo()
{
Product = prod,
ProductPricing = pPrice,
ProductExtension = prodExt
});
I have a table where I can specify add-on products (products which can be bought once the parent item has been bought).
My query to fetch these add-on products is
var addOnProductsQuery = (from pa in db.ProductAddons
where pa.EventID == eventID && pa.StatusID == 1
select new { ProductID = pa.ChildProductId });
Now what I am trying to do is filter on the query variable to only return products which are not in the addOnProductsQuery result.
Currently I have
var addOnProducts = addOnProductsQuery.ToList();
query = query.Where(e => !addOnProducts.Contains(e.Product.ProductID));
But there is a syntax error on the Contains(e.Product.ProductID)) statement
Argument 1: cannot convert from int to anonymous type: int ProductID
Chetan is right in the comments, you need to select the integer from the object before using Contains.
You can do it in 2 ways:
First you could just take the integer initially:
var addOnProductsQuery = (from pa in db.ProductAddons
where pa.EventID == eventID && pa.StatusID == 1
select new pa.ChildProductId);
This should give int as type so you can use Contains later with no problem.
Second, if you want to keep the addOnProductsQuery unchanged:
var addOnProducts = addOnProductsQuery.Select(a => a.ProductID).ToList();
query = query.Where(e => !addOnProducts.Contains(e.Product.ProductID));

Include("myTable") in Linq to Entities in Silverlight

I need help, I have a method to Access to my Orders table:
public IQueryable<Orders> GetOrders()
{
return this.ObjectContext.Orders.Include("UnitDetail");
}
it Works very well, and I can see it from the window Data Source, and can see Orders and UnitDetail from here
But I need make some considerations for the selected rows, so I made the next method:
public IQueryable<Orders> GetOpenOrders(string _iduni)
{
ObjectSet<Orders> orders = this.ObjectContext.Orders;
ObjectSet<Estatus> estatus = this.ObjectContext.Estatus;
ObjectSet<DetailUnit> units = this.ObjectContext.DetailsUnit;
ObjectSet<ServiceType> servicetype = this.ObjectContext.ServiceType;
var query =
(from o in orders
join e in estatus on o.ID equals e.IDOrder
join u in units on o.IDUni equals u.IDUni
join t in servicetype on u.IDType equals t.IDType
where o.IDUni.Equals(_iduni)
&& !estatus.Any(oe => (oe.Estatus == "CANCELADA" || oe.Estatus == "CERRADA")
&& oe.IDOrder == o.ID)
select o).Distinct();
return query.AsQueryable();
}
This show me the correct recs, but what happend? why I don't see UnitDetail, when I inspect the result UnitDetail is null, how I can do for put the Include clausule in this new method??
Thanks a lot in advance
Because you haven't put the Include in your new method anywhere.
EDITED: to remove the unused joins.
You should be able to just use Include as you did in your GetOrders method, and so have it as a part of your existing orders variable. You are not actually using those joins anywhere, are you intending to?
Like this:
public IQueryable<Orders> GetOpenOrders(string _iduni)
{
var query =
(from o in this.ObjectContext.Orders.Include("UnitDetail")
where o.IDUni.Equals(_iduni)
&& !this.ObjectContext.Estatus.Any(oe => (oe.Estatus == "CANCELADA" || oe.Estatus == "CERRADA")
&& oe.IDOrder == o.ID)
select o).Distinct();
return query.AsQueryable();
}

How to Create the Left Join by using the group by data

I have three Table One is "Allowance " ,"Balance" and "TimeoffRequests" in these three table common columns are EmployeeId and TimeoffTypeId, Now i need to get the requested hours of one leave type by grouping thier timeoffTypeId and EmployeeId from the table "TimeoffRequests" , and got the "TimeOffHours". for the i wrote the code like
var query = (from tr in TimeOffRequests
where tr.EmployeeID == 9
group tr by new { tr.EmployeeID, tr.TimeOffTypeID } into res
select new
{
EmployeeID = res.Key.EmployeeID,
TimeOffTypeID = res.Key.TimeOffTypeID,
TotalHours = res.Sum(x => x.TimeOffHours)
}).AsEnumerable();
Now I need to join these results with the first table and have to get the all the employees, and timeoffTypes from the UserAllowance and corresponding TimeoffHours from the grouped table. for getting left joined query i wrote like below.
var requestResult = (from UA in UserAllowances
join UB in UserBalances on UA.EmployeeID equals UB.EmployeeID
where UA.TimeOffTypeID == UB.TimeOffTypeID && UA.EmployeeID == 9
&& UA.TimeOffType.IsDeductableType == true // LeftJoin
join rest in query on UA.EmployeeID equals rest.EmployeeID into penidngRequst
from penReq in penidngRequst.DefaultIfEmpty()
where penReq.TimeOffTypeID == UA.TimeOffTypeID
select new EmployeeTimeOffBalanceModel
{
TimeOffTypeID = UA.TimeOffTypeID != null ? UA.TimeOffTypeID : 0,
YearlyAllowanceHrs = (UA.YearlyAllowanceHrs != null) ? UA.YearlyAllowanceHrs : 0,
BalanceHours = UB.BalanceHrs != null ? UB.BalanceHrs : 0,
PendingHours = (decimal)((penReq != null) ? (penReq.TotalHours) : 0),
EmployeeID = UA != null ? UA.EmployeeID : 0,
}).ToList().Distinct();
It is giving only timeOFfType containing in grouped data,even though I wrote leftjoin for the query using the "into" and DefaultIfEmpty() keywords. the results becomes as like:
and by using the "linqPad" editor i found that it is applying the Cross or Outer Join instead of "left join" what will be the reason.
If I remove this line of code " where penReq.TimeOffTypeID
== UA.TimeOffTypeID" this showing all the timeoffTypes with cross join with repeatation like
How can I achieve left join with tables with Grouped data and showing null values if timeofftypes didn't having the any request?
You might want to move the where clause into the the on equals clause as shown below
join rest in query on new { UA.EmployeeID, UA.TimeOffTypeID } equals new { rest.EmployeeID, rest.TimeOffTypeID } into penidngRequst
from penReq in penidngRequst.DefaultIfEmpty()
You can change
where penReq.TimeOffTypeID == UA.TimeOffTypeID
to
where penReq == null || penReq.TimeOffTypeID == UA.TimeOffTypeID

linq query with condition

I'm writing a linq query in query syntax and I'm wondering how to add another where clause.
Basically, I have the following:
var test = from t in MyDC.TheTable
where t.UserID == TheUserID
where t.DateDone.Date == TheDate.Date
select new MyModel {.....};
TheTable has a column called LinkedID and this column is also in another table called ColorStatus (a number between 1 and 10). I'm looking to write the where clause "where the LinkedID in the ColorStatus table is less than 7".
Thanks.
Just a suggestion on improving the statement you have. You can actually merge the two where conditions into a single one. && means "AND"
Where t.UserID == TheUserID && t.DateDone.Date = TheDate.Date
Your information "another table called ColorStatus" doesn't make sense here.
var test = from t in MyDC.TheTable
where t.UserID == TheUserID
&& t.DateDone.Date == TheDate.Date
&& t.LinkedID < 7
select new MyModel {.....};
Probably I didn't get your idea, here is an example of join may help you.
var test = from t in MyDC.TheTable
join x in MyDC.ColorStatus
on t.LinkedID == x.LinkedID
where t.UserID == TheUserID
&& t.DateDone.Date == TheDate.Date
&& x.AnotherField == 1
select new MyModel {.....};

C# LINQ: How to stack LINQ queries correctly

I have a form that allows the user to perform a myriad of searches. The table(s) that need to be joined differ depending on the search criteria entered. (My example below is very simplistic because both tables use the same sub-tables to join on, but the actual problem is not as simple.)
I've been using a technique I call LINQ stacking, like this:
IQueryable<LogENT> results = Context.AssignedLogsENT.Where(l => l.AgencyId);
if(txtFirstName.Text != null)
results = from r in results
join a in Context.LogAssignmentsENT on r.DisplayLogId equals a.LogId
join p in Context.PersonsENT on a.ObjectId equals p.DisplayPersonId
&& !a.Deleted &&
p.FirstName.StartsWith(Object.FirstName)
select r;
if(txtLastName.Text != null)
results = from r in results
join a in Context.LogAssignmentsENT on r.DisplayLogId equals a.LogId
join p in Context.PersonsENT on a.ObjectId equals p.DisplayPersonId
&& !a.Deleted &&
p.LastName.StartsWith(Object.LastName)
select r;
So you see if a certain text field is set, I add to the query as necessary. This actually works fine, except that when I use SQL Profiler to view the generated query, it is INNER JOINing the tables each time I add a new criterion.
i.e. the LogAssignments table is included 3, 4, 5 times. Is there a way I can prevent it from JOINing the same table more than once?
Or, is there a better way I can do this? I've looked at Predicate Builder however it doesn't seem to permit joining tables, which is a requirement in my case.
Thanks!
IQueryable<LogENT> results = Context.AssignedLogsENT.Where(l => l.AgencyId);
results = from r in results
join a in Context.LogAssignmentsENT on r.DisplayLogId equals a.LogId
join p in Context.PersonsENT on a.ObjectId equals p.DisplayPersonId
&& !a.Deleted
select r;
if(txtFirstName.Text != null)
results = from r in results
p.FirstName.StartsWith(Object.LastName)
select r;
if(txtLastName.Text != null)
results = from r in results
p.LastName.StartsWith(Object.LastName)
select r;
If you use just one query, you could modify it something like this:
results = from r in results
join a in Context.LogAssignmentsENT on r.DisplayLogId equals a.LogId
join p in Context.PersonsENT on a.ObjectId equals p.DisplayPersonId
&& !a.Deleted &&
(txtFirstName.Text != null || p.FirstName.StartsWith(Object.FirstName)) &&
(txtLastName.Text != null || p.LastName.StartsWith(Object.LastName))
select r;
You can build your base result and then dynamically add the where clauses.

Categories

Resources