Does LINQ Support Composable "OR Queries"? - linq

In another posting: Does Linq-To-Sql support composable queries there was discussion on how to compose/concat where clauses dynamically. This appears to be done with an "AND" (i.e. the first where clause and the second where clause are joined by an AND). What I am wondering is if there is a way to compose Linq queries with an OR.
Example:
var people = from p in Person
where p.age < 18
select p
var otherPeople = from p in people
where p.firstName equals "Daniel"
select p
This gives people with a first name of "Daniel" and that are under 18. I'm looking for the syntax to join these to find people who have a first name of "Daniel" or are under 18.
Note: I am using ADO.net Data Services so I do not have .Contains() available to me.
EDIT: The Union Suggestion (by Garry Shutler) is exactly what I am looking for functionality-wise. I did run into two possible issues with it:
It looks like it would make multiple database hits if I was to do a third condition (union seems to take an IEnumerable as its parameter) - I was hoping to build up multiple AND and OR statements in code and then execute one request.
Union is not supported by ADO.Net Data Services (very disappointing)

Is what you want as simple as:
var people = from p in Person
where p.age < 18 || p.firstName == "Daniel"
select p;
or have you just given a simple example?
In which case you can use:
var under18 = from p in Person
where p.age < 18
select p;
var daniels = from p in Person
where p.firstName == "Daniel"
select p;
var combined = under18.Union(daniels);
LinqToSql may be intelligent enough to convert that to an OR but I'm not so sure.

What about using PredicateBuilder by Joe Albahari?
var predicate = PredicateBuilder.False<Person>();
predicate = predicate.Or(p => p.age < 18);
predicate = predicate.Or(p => p.firstName == "Daniel");
var query = Person.Where(predicate);

The predicate option is the way to go. The Union option DOES NOT build good sql. Reference http://social.msdn.microsoft.com/forums/en-US/linqprojectgeneral/thread/925b245d-5529-4a64-8cd4-4bc83ee6fe7a/

I wrote about how to achieve queries which search for a key value within a set on my blog .
Here are the relevant links.
Contains Operations in ADO.NET Data Services Part I
Contains Operations in ADO.NET Data Services Part II
Using this , you can write queries which look like this
//The set in which we have to search for a match
List<string> citiesIWillVisit = new List<string>() {"London","Berlin","Prague"};
var customersAround = nwContext.Customers
.IsIn<Customers>(citiesIWillVisit, c=> c.City);
foreach (Customers localCustomer in customersAround) {
System.Console.WriteLine(localCustomer.ContactName);
}

Related

What tools are there that help build expression trees for dynamic LINQ queries?

My project needs to let users build their own dynamic queries. From what I've read, Expression Trees are the way to go. However the syntax is rather complicated.
I envision having a GUI where users would be able to check tables, select columns, specify parameters,etc and then build a string such as:
var myQuery =
from P in context.Projects
join UA in context.UserAttributes on P.ProjectID equals UA.ProjectID
join UBA in context.UserBooleanAttributes on UA.UserAttributeID equals UBA.UserAttributeID
join U in context.Users on UBA.UserID equals U.UserID
where P.ProjectID == 1
where UBA.Value == true
where (UA.UserAttributeID == 1 || UA.UserAttributeID == 2)
select new { uba = U };
And store that in a queries table. To process the query, I was hoping there is some library out there that will magically do something like:
var result = magic(str);
foreach(var user in result)
Foo(user.Email);
In this example I know that all my queries would return Users, but for other queries I would probably have to use reflection or in another column specify the expected type in results.
I found one project called LinqTextQueryBuilder which looks interesting, but I wanted to see if there are other alternatives.

Entity Framework LINQ query construction

I'm learning EF and LINQ while working on an API for a project
While in most case EF and LINQ made my coding easier this specific case is different.
I have a list of integers and i have to query my DB including all int inside
the list [10,2,23]
var queryable = (from p in db.plants
where p.plant_id == 10
|| p.plant_id == 2
|| p.plant_id == 23
select p)
.ToList();
but the list is created at runtime and the number of items inside is variable
so what's the method to use for creating the query?
You can use the Contains() function on an IEnumerable of your required ids. Entity Framework will convert this to a SQL IN clause so that it is an nice efficient query.
So this would lead your example to be:
var plantIds = new List<int> {10, 2, 23};
var queryable = (from p in db.plants
where plantIds.Contains(p.plant_id)
select p)
.ToList();

Combining LINQ Queries to reduce database calls

I have 2 queries that work, I was hoping to combine them to reduce the database calls.
var locations = from l in db.Locations
where l.LocationID.Equals(TagID)
select l;
I do the above because I need l.Name, but is there a way to take the above results and put them into the query below?
articles = from a in db.Articles
where
(
from l in a.Locations
where l.LocationID.Equals(TagID)
select l
).Any()
select a;
Will I actually be reducing any database calls here?
This seems a bit complicated because Locations appears to be a multi-value property of Articles and you want to only load the correct one. According to this answer to a similar question you need to use a select to return them separately in one go so e.g.
var articles = from a in db.Articles
select new {
Article = a,
Location = a.Locations.Where(l => l.LocationId == TagId)
};
First failed attempt using join:
var articlesAndLocations = from a in db.Articles
join l in a.Locations
on l.LocationID equals TagID
select new { Article = a, Location = l };
(I usually use the other LINQ syntax though so apologies if I've done something stupid there.)
Could you not use the Include() method here to pull in the locations which are associated with each article, then select both the article and location object? or the properties you need from each.
The include method will ensure that you don't need to dip into the db twice, but will allow you to access properties on related entities.
You would need to use a contains method on an IEnumerable I believe, something like this:
var tagIdList = new List() { TagID };
var articles = from a in db.Articles.Include("Locations")
where tagIdList.Contains(from l in a.Locations select l.LocationID)
select new { a, a.Locations.Name };
(Untested)

How do I use Like in Linq Query?

How I can use Like query in LINQ ....
in sql for eg..
name like='apple';
thanks..
Use normal .NET methods. For example:
var query = from person in people
where person.Name.StartsWith("apple") // equivalent to LIKE 'apple%'
select person;
(Or EndsWith, or Contains.) LINQ to SQL will translate these into the appropriate SQL.
This will work in dot notation as well - there's nothing magic about query expressions:
// Will find New York
var query = cities.Where(city => city.Name.EndsWith("York"));
You need to use StartsWith, Contains or EndsWith depending on where your string can appear. For example:
var query = from c in ctx.Customers
where c.City.StartsWith("Lo")
select c;
will find all cities that start with "Lo" (e.g. London).
var query = from c in ctx.Customers
where c.City.Contains("York")
select c;
will find all cities that contain "York" (e.g. New York, Yorktown)
Source
name.contains("apple");
I use item.Contains("criteria"), but, it works efficiently only if you convert to lower both, criteria and item like this:
string criteria = txtSearchItemCriteria.Text.ToLower();
IEnumerable<Item> result = items.Where(x => x.Name.ToLower().Contains(criteria));

Linq filter collection with EF

I'm trying to get Entity Framework to select an object and filter its collection at the same time. I have a JobSeries object which has a collection of jobs, what I need to do is select a jobseries by ID and filter all the jobs by SendDate but I can't believe how difficult this simple query is!
This is the basic query which works:
var q = from c in KnowledgeStoreEntities.JobSeries
.Include("Jobs.Company")
.Include("Jobs.Status")
.Include("Category")
.Include("Category1")
where c.Id == jobSeriesId
select c;
Any help would be appreciated, I've been trying to find something in google and what I want to do is here:http://blogs.msdn.com/bethmassi/archive/2009/07/16/filtering-entity-framework-collections-in-master-detail-forms.aspx
It's in VB.NET though and I couldn't convert it to C#.
EDIT: I've tried this now and it doesn't work!:
var q = from c in KnowledgeStoreEntities.JobSeries
.Include("Jobs")
.Include("Jobs.Company")
.Include("Jobs.Status")
.Include("Category")
.Include("Category1")
where (c.Id == jobSeriesId & c.Jobs.Any(J => J.ArtworkId == "13"))
select c;
Thanks
Dan
Include can introduce performance problems. Lazy loading is guaranteed to introduce performance problems. Projection is cheap and easy:
var q = from c in KnowledgeStoreEntities.JobSeries
where c.Id == jobSeriesId
select new
{
SeriesName = c.Name,
Jobs = from j in c.Jobs
where j.SendDate == sendDate
select new
{
Name = j.Name
}
CategoryName = c.Category.Name
};
Obviously, I'm guessing at the names. But note:
Filtering works.
SQL is much simpler.
No untyped strings anywhere.
You always get the data you need, without having to specify it in two places (Include and elsewhere).
No bandwith penalties for retrieving columns you don't need.
Free performance boost in EF 4.
The key is to think in LINQ, rather than in SQL or in materializing entire entities for no good reason as you would with older ORMs.
I've long given up on .Include() and implemented Lazy loading for Entity Framework

Resources