System.Linq.Dynamic - Can I use IN clause in WHERE statement - c#

I have dynamic linq WHERE statement:
dataContext.Table.Where("id = 0 Or id = 1 Or id = 2 Or ...");
I want change to:
dataContext.Table.Where("id IN (0, 1, 2, ...)");
But it doesn´t work. How can I do this for better performance?

From How to use “contains” or “like” in a dynamic linq query?
//edit: this is probably broken, see below
ids = new int[] {1,2,3,4};
dataContext.Table.Where("id.Contains(#0)", ids);
Aside: It is good practice to use placeholders in dynamic linq expressions. Otherwise you may open yourself to linq injection attacks (Is Injection Possible through Dynamic LINQ?)
EDIT:
actually I think I messed this up.
Unfortunately I cannot test this at the moment.
But I think the correct syntax in this case should be dataContext.Table.Where("#0.Contains(id)",ids);, not the other way around, and that version does not work out-of-the-box.
See here for a way to add this functionality to dynamic link. You need to modify the library for this.

var ids = new int[] {1,2,3,4};
dataContext.Table.Where(f => ids.Contains(f.id))

it seems that in version 1.0.4 of System.Linq.Dynamic , we can use the following syntax dataContext.Table.Where("#0.Contains(outerIt.id)",ids); as it was made and presented in the already cited blog:
here

Related

Using StringCollection specified in Application Settings in a LINQ-to-Entities Query

In my application, I have Property Setting which is of type String.Collections.Specialized.StringCollection. It contains a list of customer codes such as MSFT, SOF, IBM etc. I'm trying to use this in a Linq-to-Entities query in the where clause:
var ShippedOrders = dbcontext.Orders
.Where(s=>(s.Status.Description.Equals("Shipped") && !Properties.Settings.Default.CustomersToExclude.Contains(s.CustomerCode)));
This fails as Contains is not recognized by Linq-to-Entities with a message similar to:
"LINQ-to-Entities does not recognize the method Contains...."
How do I revise the code above to avoid this error?
A shorter path is
myProperties.Settings.Default.CustomersToExclude.Cast<string>().Contains(blah);
That's a handy trick for any situation where a collection isn't inherently LINQ-aware.
Since your question is tagged as C# 4 use a List<string> instead (StringCollection is ancient) and your query should work. Also you should resolve your list reference outside your query:
List<string> customersToExclude = ..
var ShippedOrders = dbcontext.Orders
.Where(s=>(s.Status.Description.Equals("Shipped")
&& !customersToExclude.Contains(s.CustomerCode)));
Edit:
Just copy your customers to an array and use that:
var customerstoExclude = new string[Properties.Settings.Default.CustomersToExclude.Count];
myProperties.Settings.Default.CustomersToExclude.CopyTo(customerstoExclude, 0);
This is answered in a related question. EF4 apparently supports Contains directly, though, so that'd be my prefered solution... :)

best way to build the dynamic linq queries in c#?

I want to know which is the best way to build dynamic queries in LINQ. Queries will be complex and nested. While searching I found a few ways:
Linq dynamic (System.Linq.Dynamic)
Albahari's Predicate builder class
Linq.Expression
There may be more options than these. Which is the best way?
This depends on your circumstances: how fast do you need it, what is your starting point, and so on. In an unconstrained world, I think the best thing is to roll your own library for building dynamic queries. You can use Scott's or Joseph's work as an inspiration, but in the end it all "bottoms out" in the Linq.Expression library.
One advantage to the "do it yourself" approach is that you would not need to bridge from your code to someone's framework. Rather, you would code directly to .NET APIs. This may be useful when you already have a representation of your dynamic queries, for example, in a model that you present to users through a UI, in an XML file, etc. All you need is to walk that representation recursively, and produce System.Linq.Expression as the return.
FWIW, my company took this approach when .NET 3.5 came out, and we are very happy with the outcome.
Linq queries can be written in two ways and let you use any kind of nesting.
Query Syntax
IEnumerable<int> numQuery1 =
from num in numbers
where num % 2 == 0
orderby num
select num;
Method Syntax
IEnumerable<int> numQuery2 = numbers.Where(num => num % 2 == 0).OrderBy(n => n);
For more information about Linq, you can visit Microsoft's LINQ (Language-Integrated Query). It contains everything from getting started to sample tutorials

How to create LINQ Query from string?

I am new at LINQ and really need a help with some coding.
At the moment, I have a string and a var variables.
string temp = "from product in myEntities.Products where product.Name.Contains(_Name) select product";
var _Products = temp;
LvProducts.DataSource = _Products;
LvProducts.DataBind();
Basically, what I want to do is to be able to create a custom/complicated LINQ query by assigning it into a string beforehand. After done with composing, I assign the string into the var variable. However, this is obviously will not work. Therefore, can anyone assist me on this?
You have a few options:
Use the the Dynamic Linq
libraries to construct you queries on
the fly. The best place to get
started is by reading ScottGu's blog
entry. However, I don't think
these libraries support the contains
method in your example. Here is
a blog post explaining how to add
this support.
Directly execute SQL statements. Check out the MSDN docs for Linq to Sql or Linq to Entities.
var _Products = myEntities.ExecuteStoreQuery<Product>
(#"SELECT * FROM Products WHERE [Name] In ('Item1', 'Item2')");
Use Linq's composable behaviour. This might not be the most elegant solution but it works really well if you do not have too many options. You can just construct your query in multiple parts.
var _Products = from product in myEntities.Products
select product
_Products = from product in _Products
where product.Name.Contains(_Name)
select product
if FilterByPrice {
_Products = from product in _Products
where product.Price > 100
select product
}
You can do this by compiling this Linq within some c# using the CodeDomProvider - Adding scripting functionality to .NET applications - but this is quite heavyweight as a solution. If you want to see more about how to do this, then take a look at LinqPad - http://www.linqpad.net - the author invites you to use the decompiler to see how it works!
If the requirement is just down to simple where clauses than an alternative might be to use Dynamic Linq - see Scott Gu's posts and the sample code from Microsoft - http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
Maybe this can help you
http://nlinq.codeplex.com/
BR.
Much of the reason you use LINQ in the first place is to get compiler-verified queries, that wil ldetect errors at compile time. This will defeat that purpose since the string will be parsed at runtime.
For your needs you have two options:
1) Making a eSQL query and running it on the ObjectContext. Using this, you can still use your entities like myEntities.Products, and return a list of products.
2) Using a normal SQL query, and use the ObjectContext to call that directly towards the underlying database.
My guess is that you will have to use dynamic code execution. For further details, have a look at Ricks post on west-wind.
you're thinking of it like a Dynamic SQL where you create the statement as string and parse it as a SQL statement.
Since you're already in the code, why not make the statements right in there. It would be a lot easier if you use Lambda instead of the traditional linq. my 2 cents.

c# Fluent SQL Helper - Syntax improvement

I'm writing a little library to help building SQL requests (only doing SELECTs for the moment) but I'm not satisfied with an aspect of the syntax, here's an exemple to explain:
var db = FluentDb.WithConnectionString("SqlCeTest");
var query = db.From("Customers")
.Where(FS.Col("Age") > 18 & FS.Col("Name").StartsWith("L"))
.OrderBy("BirthDate")
.Select("Name", "Age", "BirthDate");
var customers = query.ToList((r) => new
{
Name = r.Get<string>("Name"),
Age = r.Get<int>("Age"),
BirthDate = r.Get<DateTime?>("BirtDate")
});
The part I'd like to improve is the FS.Col("ColumnName"), it's supposed to stand for FluentSql.Column (return a new FluentColumn(columnName)), but I find it a bit long in that context, what I'd really like is to be able to use just Col("ColumnName")...
Do anybody see a trick I could use to achieve that, or another syntax idea?
My ideas:
Extension method on string: Where("Name".Col() == "Jon")
Lambda expression with factory object using indexer: .Where(c => c["Name"] == "Jon")
Anyone see something better/shorter/nicer?
Edit:
my second idea looks good but there's a downside if i use it in another context:
I sometime need to use FluentColumns in Select (or OrderBy, or GroupBy) statements like that:
query.Select(FS.Col("Name").As("Customer"), FS.Col("OrderId").Count().As("OrdersCount"));
I would have to repeat the 'c => ' for each column...
A twist on your second option (which is pretty good) would be to use a dynamic expandoobject in the lambda instead of a string indexer.
http://blogs.msdn.com/b/csharpfaq/archive/2009/10/01/dynamic-in-c-4-0-introducing-the-expandoobject.aspx
Just for information, I decided to go with an indexer syntax on the FluentDb instance:
db["Customer", "AddressId"] mean column AddressId of table Customer,
an alternative syntax is available: db["Customer"]["AddressId"]
So in the end, it's gonna be (I still need to find a trick to make the Column declaration without table nice):
.Where(db["Customer", "Name"] == "Jon")

Dynamically adding select fields using LINQ lambda

Lets say we have an expression:
var prices = from p in PriceDB.Prices
where p.TypeID == 12
orderby p.PriceType.Title
select p;
Is it possible to modify the select list?
I imagine it looking something like this:
var newPriceList = prices.Select( p => p.ExchangeRate );
This may be an odd request, but in my code (which is too long and complex to post here) I want to conditionally add fields to be output depending on a CheckBoxList.
I assume, of course, that I'm trying to go about this the wrong way...
I imagine it looking something like this:
Actually it would look exactly like that. First, build a query, selecting the entire record. Then add a select (using the Select() method seem the easiest way) to limit the selection. Linq-to-Sql will sort out the two selects, and use the proper reselt, so theres just one select in the final SQL.
There's no really good way to choose between multiple selects. I would probably use a switch/case.
While you could go down the dynamic route, I would strongly consider not doing so. What is the cost of fetching the extra values if you don't need them, in your particular case? Is the problem that they're being displayed dynamically and you only want them displayed in certain cases? If so, I'd suggest modifying the display code somehow.
It's hard to stay strongly typed (which has various advantages) while being dynamic in terms of what you fetch. Of course, if you always want to fetch the same "shape" of data (e.g. always just a decimal value from each row) then that's reasonably easy - let me know if that's something you'd like to see demonstrated.
If you could tell us more about your problem, we may be able to suggest alternative solutions.
If I understood you correct this is explaining how to build dynamic queries:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
You might want to look at this Dynamic LINQ and Dynamic Lambda expressions?
Or the Dynamic Expression API (System.Linq.Dynamic).

Categories