Apply dynamic where clause to joined table - c#

I need to build a LINQ query that allows me to vary the where clause on a joined table but can't find a way to do it.
A simplified example of the two queries I'm constructing are:
var myQuery = from tab1 in context.Table1
join tab2 in context.Table2 on Table1.ID equals Table2.Table1ID
where tab1.TypeCode == 3
tab2.SomeID == 4 &&
select tab1.ID;
var myQuery2 = from tab1 in context.Table1
join tab2 in context.Table2 on Table1.ID equals Table2.Table1ID
where tab1.TypeCode == 3
tab2.SomeOtherID == 4 &&
select tab1.ID;
The only difference between them being the tab2.SomeID where clause changes to tab2.SomeOtherID.
If the changing where clause was being applied to tab1 I could just add a .Where to the query but how do I use a common query and specify a different tab2 where clause?

Dynamically Composing Expression Predicates
or
(source: scottgu.com)
You need something like this? Use the Linq Dynamic Query Library (download includes examples).
Check out ScottGu's blog for more examples.

You can have optional parameters in queries:
int? someID = null;
int? someOtherID = 4;
var myQuery = from tab1 in context.Table1
join tab2 in context.Table2 on Table1.ID equals Table2.Table1ID
where tab1.TypeCode == 3
&& (someID == null || tab2.SomeID == someID)
&& (someOtherID == null || tab2.SomeOtherID == someOtherID)
select tab1.ID;
Linq-to-SQL will eliminate the parts that can be evaluated client-side from the query, so in the above example the where clause will filter on tab1.TypeCode and tab2.SomeOtherID.

Related

Need multiple where conditions to a query with OR operator

I have a requirement to add multiple where conditions with or operator out of which one where condition will have to check if the db column has any of the item in a list provided. Please consider the query below
var res= from table1 in context.table1
join table2 in context.table2
on table1.id equals table2.id
where table1.name=="res1" || table1.description=="desc"
|| table1.name.any(res=>FreeText.Contains(res))
select table1
this query is leading the compiler to run query multiple times and I am not getting required result. My end goal is to achieve the following sql query
select * from table1 join table2 on table1.id ==table2.id
where table1.name=="res1" || table1.description=="desc" || table1.name like "%item1%" ||table1.name like "%item2% ......"
the like statements should be dynamically added based on the items in the list.
try this...
var res= from table1 in context.table1
join table2 in context.table2
on table1.id equals table2.id
where table1.name=="res1" || table1.description=="desc"
|| FreeText.Any(p => table1.name.Contains(p, StringComparison.InvariantCultureIgnoreCase))
select table1

Using Left Outer Join in Linq

I want to write one LINQ query with left outer join.For this I am able to write the corresponding SQL query which returns the desired output but the same in linq doesn't work for me.
This what my SQL looks like:
SELECT Table1.ID, Table1.Description
FROM Table1 LEFT OUTER JOIN
Table2 ON Table1.AID = Table2.AID AND Table1.TID = Table2.TID
WHERE (Table2.Status <> 'Using') OR (Table.Status IS NULL)
This query returns 7 records for me and that is what my requirement is.Now the same query I want to write with LINQ and this is what I tried with:
return (from t1 in db.Table1.AsEnumerable()
join t2 in db.Table2.AsEnumerable() on t1.AID equals t2.AID into outer
from item in outer.DefaultIfEmpty()
where item.TID == t1.TID
&& string.IsNullOrEmpty(item.Status) || item.Status != "Using"
select t1
);
But I have been facing issues with this.Here , it is not able to find item and thus returning
'Object reference not set to an instance of an object.'
What am I doing wrong over here????
I have been trying continuously but ended up with no solutions . So, any help in this would be highly appreciated.Thanks in advance..
Your SQL and LINQ statement are not the same, you have a different join clause.
Try this:
from t1 in db.Table1
join t2 in db.Table2 on new {
aID = t1.AID,
tID = t2.TID
}
equals new {
aID = t2.AID,
tID = t2.TID
} into outer
from item in outer.DefaultIfEmpty()
where item.Status == null || item.Status != "Using"
select t1
You can add multipe join relations with the new {} equals new {} statement.
DefaultIfEmpty returns a collection containing a single, default item if there is nothing in the collection.
As your entities are probably classes rather than structs, that means you get a collection with a single null in it, not a collection with a single item in it with null fields.
As well as the join clause change suggested by Loetn, you should also change your where condition to
where item == null || item.Status != "Using"

Select from multiple tables using linq

I am trying to execute the following SQL statement using linq:
SELECT TTT.SomeField
FROM Table1 as T, Table2 as TT, Table3 as TTT
WHERE (T.NumberID = 100 OR T.NumberID = 101)
AND T.QuestionID = 200
AND T.ResponseID = TT.ResponseID
AND TT.AnswerID = TTT.AnswerID
Essentially getting one field from a third table based on primary/foreign key relationships to the other 2 tables. It is expected to have a single result every time.
var query = from t in db.Table1
join tt in db.Table2 on t.ResponseID equals tt.ResponseID
join ttt in db.Table3 on tt.AnswerID equals ttt.AnswerID
where (t.NumberID == 100 || t.NumberID == 101) && t.QuestionID == 200
select ttt.SomeField
If you always expect single result, you can wrap this in ().Single(), or, if there might be no results found, in ().SingleOrDefault().
If I understand you correct. You should read something about Joins I guess.
here

LINQ equivalent for SQL

I am trying to convert a ASP.NET project to Entity framework. How to re-write the following query to its LINQ equivalent?
SELECT {Table1 objects}
FROM [Table1] tb1
INNER JOIN [Table2] tb2
ON tb1.Table1ID = tb2.fk_Table1ID
WHERE tb2.fk_attrib1 = '123' AND tb2.fk_attrb2 = '345'
ORDER BY tb1.attrib1
The result is a collection of Table1 objects.
Here Table1 and Table2 correspond to object System.Data.Objects.ObjectSet of ADO.NET Entity Framework.
var results = from tb1 in Context.Table1
join tb2 in Context.Table2 on tb1.Table1ID == tb2.fk_Table1ID
where tb2.fk_attrib1 == "123" && tb2.fk_attrb2 == "345"
orderby tb1.attrib1
select tb1;
Something like this:
context.Table1
.Where( o => o.Table2s.Any( o2 =>
o2.fk_attrib1 == '123' &&
o2.fk_attrib2 == '345' ) )
.OrderBy( o => o.attrib1 )
.ToList();
BTW, LINQPad is great for trying out L2E queries.
This should help you a little bit. I suppose the main problem is with JOIN clause - in EF you can use NavigationProperties and don't need to worry about joining tables - EF will take care of that for you.
Also you are trying to filter on column from joined table. This you can do using Any method to find all Table1 elements that are connected to Table2 where those referenced elements have certain properties/columns. You should also get familiar with All method, as it might be useful to you in future.
from t1 in context.Table1
where t1.Table2s.Any(t2.fk_attrib1 == "123" && t2 => t2.fk_attrb2 == "345")
order by t1.attrib1
select t1;
Edit:
I assume that there is 1:n relationship between Table1 and Table2 which results in enumerable collection as NavigationProperty in Table1 objects.
Edit2:
Fixed error in code - didn't noticed that both attributes are from Table2 not Table1
Should be something like this:
var result = (from tb1 in Table1
from tb2 in Table2
where tb1.Key == tb2.Key &&
tb2.fk_attrib1 = '123' &&
tb2.fk_attrb2 = '345'
select ione).OrderBy(p=>p.attrib1);
Hope this helps.

LINQ statement with 2 inner joins

Actually I think I might have fixed it, gonna do some testing, I wll post my solution if it works.
I am migrating an older DB system over to LINQ, I'm having trouble converting a few of the SQL statements though:
SELECT * FROM cities
INNER JOIN deals ON cities.cityId = deals.CityID
INNER JOIN countries ON cities.countryID = countries.CountryId
WHERE deals.endDate >= (someDate)
AND countries.CountryId = (1)
AND deals.soldout = (false)
I've done some research, but I can't get it to work. Here is the LINQ statement I came up with:
var deals = from d in db.deals
join city in db.cities on d.CityID equals city.cityId
join country in db.countries on city.countryID equals country.CountryId
where d.endDate > DateTime.Today && country.CountryId == 1 && d.soldOut == false
select d;
Is there some particular way to use 2 joins in LINQ?
Sorry, I had a formatting error: the statement is meant to select all the deals that have a city who's countryID = 1
You do not need the 2nd join if you have a country code for the city...
var deals = from d in db.deals
join city in db.cities on d.CityID equals city.cityId
where d.endDate > DateTime.Today &&
city.CountryId == 1 && d.soldOut == false
select d;
If you want columns from all tables involved, you can use an anonymous type for that.
select new {d, city, country}

Categories

Resources