Linq: Simple Boolean function returns linq Exception - linq-to-sql

I have a Linq query that looks something like this:
var query = from x in table where SomeFunctionReturnsBool() select;
private bool SomeFunctionReturnsBool()
{
return true;
}
This returns and exception that says "SomeFunctionReturnsBool has no supported translation to SQL". I get that this is because it wants to treat "SomeFunctionReturnsBool" as an expression to evaluate as SQL, but it can't.
Although this Linq query isn't complicated, the real ones are. How can I accomplish what I'm trying to do here, which is to break out pieces of the query to hopefully make it more readable?
Jeff
UPDATE
Good answers. I am trying now to work with expressions instead, but this code gets me "cannot resolve method Where(lambda expression)":
var query = from x in table where SomeFunctionReturnsBool() select x;
private Expression<Func<EligibilityTempTable, bool>> SomeFunctionReturnsBool
{
return (x) => true;
}

Another way is to use Expression<Func<YourType, bool>> predicate...
var query = from x in table where SomeFunctionReturnsBool() select;
Edit: I don't usually do it the way I've shown above... I was just getting that from the code above. Here is the way I usually implement it. Because then you can tack on additional Enumerable methods or comment them out during debugging.
var results = table.Where(SomeFunctionReturnsBool())
.OrderBy(yt => yt.YourProperty)
//.Skip(pageCount * pageSize) //Just showing how you can easily comment out parts...
//.Take(pageSize)
.ToList(); //Finally executes the query...
private Expression<Func<YourType, boo>> SomeFunctionReturnsBool()
{
return (YourType yt) => yt.YourProperty.StartsWith("a")
&& yt.YourOtherProperty == true;
}
I prefer to use the PredicateBuilder which allows you to build an expression to be used in your Where...

You can do this in LINQ-to-SQL by creating a UDF mapped to the data-context; this involves writing TSQL, and use ctx.SomeFunctionblah(...).
The alternative is to work with expression trees - for example, it could be:
Expression<Func<Customer, bool>> SomeFunc() {
return c => true; // or whatever
}
and use .Where(SomeFunc()) - is that close enough? You can't use the query syntax in this case, but it gets the job done...
Added dodgy Where method to show how you might use it in query syntax. I don't suggest this is fantastic, but you might find it handy.
using System;
using System.Linq;
using System.Linq.Expressions;
static class Program
{
static void Main()
{
using (var ctx = new NorthwindDataContext())
{
ctx.Log = Console.Out;
// fluent API
var qry = ctx.Customers.Where(SomeFunc("a"));
Console.WriteLine(qry.Count());
// custom Where - purely for illustration
qry = from c in ctx.Customers
where SomeFunc("a")
select c;
Console.WriteLine(qry.Count());
}
}
static IQueryable<T> Where<T>(this IQueryable<T> query,
Func<T, Expression<Func<T, bool>>> predicate)
{
if(predicate==null) throw new ArgumentNullException("predicate");
return query.Where(predicate(default(T)));
}
static Expression<Func<Customer, bool>> SomeFunc(string arg)
{
return c => c.CompanyName.Contains(arg);
}
}

Basically, "out of the box", you can't have LINQ-to-SQL execute queries that have custom functions in them. In fact only some native methods that can be translated to SQL can be used.
The easiest way around this can unfortunately affect performance depending on how much data you're bringing back from the DB.
Basically, you can only use custom functions in WHERE statments if the data has already been loaded into memory, i.e, SQL have already executed.
The quickest fix for your example would look like this:
var query = from x in table.ToList() where SomeFunctionReturnsBool() select;
Notice the ToList(). It executes the SQL and puts the data into memory. You can now do whatever you want in the WHERE statement/method.

I would just break them out like so:
Expression<Func<Table, bool>> someTreeThatReturnsBool = x => true;
var query = from x in table where someTreeThatReturnsBool select x;
You could create functions that pass around expression trees.

Don't use query syntax for this.
var query = table.Where( x => SomeFunction(x) );

Related

LINQ for SQL statement that returns single scalar value

I want to execute the following select:
SELECT 0 as Value
What is the correlating syntax in LINQ for SQL?
Edit
I want to use the correlating LINQ for SQL statement in a Concat() call like this
var c = (from a in mytable select a.Value).Concat(select 0).Sum();
As you can see, Concat(select 0) obviously doesn't compile. Any ideas?
Edit 2
David suggested to use a simple collection instead. I've tried
private decimal[] mZeroDecimals = new[] { 0.0m };
...
public void MyFunction()
{
var c = (from a in mytable select a.Value).Concat(mZeroDecimals).Sum();
...
but it throws an exception Local sequence cannot be used in LINQ to SQL implementation of query operators except the Contains() operator.
You're not actually querying anything, so there is no LINQ involved. You're just creating an anonymous object with a single property called Value:
var obj = new { Value = 0 };
Edit: Based on your comment, it sounds like you want this object in a collection. That doesn't make it a LINQ query (since you're still not querying anything), but you can declare a collection just as easily as a single object. Something like this:
var coll = new[] { new { Value = 0 } };
Since this is a collection, it can be used with any of the enumerable extension methods that LINQ uses, which sounds like what you're trying to do.

Entity Framework 5 - T4 generated context class causing 'duplicate parameter name'

I'm using EF5.0 in an ASP.NET MVC app. My Entity Model is named 'DataModel'. Included in the model is a table-valued function that exists in my MSSQL database, named MatchingEntries. It returns a table of integer ids.
I've looked at the DataModel.Context.cs file, that gets generated via the .tt (T4) template file. It has the following code in it:
[EdmFunction("DataEntities", "MatchingEntries")]
public virtual IQueryable<Nullable<int>> MatchingEntries(string term)
{
var termParameter = term != null ?
new ObjectParameter("Term", term) :
new ObjectParameter("Term", typeof(string));
return ((IObjectContextAdapter)this).ObjectContext.CreateQuery<Nullable<int>>("[DataEntities].[MatchingEntries](#Term)", termParameter);
}
The error I am getting results from using this method twice within the one query, such as:
IQueryable<int> one = db.MatchingEntries("\"one*\"");
IQueryable<int> two = db.MatchingEntries("\"two*\"");
List<int> both = one.Intersect(two).ToList();
The error is:
A parameter named 'Term' already exists in the parameter collection. Parameter names must be unique in the parameter collection.
Parameter name: parameter
Is this a known limitation of the classes generated from an EDMX for table-valued functions? With LINQ2SQL I am able to execute this a a single query to the database (that does a JOIN between the 2 outputs from MatchingEntries) and it replaces the parameter name #Term with #p0 and #p1 for the two different instances of the call. I'd like to make Entity Framework do the same.
So, my question is, how can I get EF to work in the same manner and avoid the 'Duplicate parameter' error?
My fallback is to evaluate each call to db.MatchingEntries separately, by putting ToList() after them. My other idea has been to replace the ObjectParameter name in the T4 generated Context.cs class with something randomly generated each time. These feel like hacks that I should be able to avoid.
This answer is Linq to Entities specific. This doesn't have to be done in Linq to SQL (Linqpad).
Thanks to this question I got a pointer to a viable solution:
extend the autogenerated DBContext class (partial class)
add a method with two parameters in the partial class
at calling, pass an index as second parameter
Detailed Answer:
DataEntitys.my.cs:
[EdmFunction("DataEntities", "MatchingEntries")]
public virtual IQueryable<Nullable<int>> MatchingEntries(string term, int index)
{
string param_name = String.Format("k_{0}", index);
var termParameter = term != null ?
new ObjectParameter(param_name, term) :
new ObjectParameter(param_name, typeof(string));
return ((IObjectContextAdapter)this).
ObjectContext.CreateQuery<Nullable<int>>(
String.Format("[DataEntities].[MatchingEntries](#{0})", param_name),
termParameter);
}
Call the function:
foreach (string teil in such)
{
index++;
if (teil.Trim() != "")
res = res.Join(db.MatchingEntries("\"" + teil + "*\"", index), l => l.ID, s => s.KEY, (l, s) => l);
}

Using Nihibernate with system dynamic linq for Query<T>

I am trying to use system.dynamic.linq to create dynamic sorting.
this, is the query that I use:
var query = dalSession.Query<T>().AsQueryable();
var res = (from x in query orderby "x.FirstName" select x)
this is the mysql output:
select
affiliate0_.id as id0_,
affiliate0_.first_name as first6_0_,
from affiliate affiliate0_ order by 'x.FirstName' //FirstName as well
So you can see that the output went to the mysql query is the direct string, and not its reflection, ('x.FirstName') or ('FirstName').
This has no meaning in mysql context, it looks like I need order by affiliate0_.first_name.
Is there anyway to provide the Nhibernate the member itself? So the compiled query will be done normally?
You have to remove the " from you requiry. "x.FirstName" is seen as a string and translated to a sql string.
The "x" has no meaning inside the dynamic string.
Remove the x. (i.e. leave just "FirstName") and it should work.
Using a method call instead of the query comprehension syntax, you'd get:
var res = query.Orderby("FirstName")
Did you try it as follows (as Diego suggested)?
(from x in query select x).OrderBy("FirstName")
Because I think the dynamic linq orderby extension method is not executed when you use (x => "FirstName")
Otherwise try this:
(from x in query select x).OrderBy("it.FirstName")
BTW I renamed the OrderBy method in Dynamic.cs to DynamicOrderBy because I had some situations where the not dynamic linq OrderBy method was executed too:
public static IQueryable<T> DynamicOrderBy<T>(this IQueryable<T> source, string ordering, params object[] values) and use that one instead:
(from x in query select x).DynamicOrderBy("FirstName")
var param = Expression.Parameter("x");
var prop = Expression.Property(param, "FirstName");
var lambda = Expression.Lambda<Func<User, string>>(prop, param);
query.Orderby(lambda);

How to aggregate IEnumerable<string> to string using Linq Aggregate function

I have Ienumerable<string> collection that I want to concatenate into a single string with delimitor ;
for instance {"One","Two","Three"} -> "One;Two;Three;"
is it possible to do using the following function?
List<string> list = new List<string>(){"One","Two","Three"};
list.Aggregate<String>((x,y) => x + String.Format("{0};",y));
I have tried also this code:
list.Aggregate<String>((x,y) => String.Format("{0};{1}",x,y));
both samples didn't work.
EDIT: I see that it is not possible to do what I wanted using Linq-2-sql or Aggregate function in Linq-2-sql.
http://social.msdn.microsoft.com/forums/en-US/linqprojectgeneral/thread/dac496c0-5b37-43ba-a499-bb8eff178706/
EDIT2: the workaround I used is to go over the items returned by the original linq query...and copies them to a new list and do the join as suggested in the answers below on a linq object and not linq-2-sql object.
You can just use String.Join for this. If you're using .NET4 then you can use the overload that takes an IEnumerable<string> directly:
string joined = string.Join(";", list);
If you're using an older version of the framework then you'll need to use the overload that takes a string[] array instead, converting your collection to an array first if necessary:
string joined = string.Join(";", list.ToArray());
EDIT...
Of course, if you really want to use Aggregate for some reason then there's nothing stopping you. If so, it's usually recommended to build your string using a StringBuilder rather than multiple string allocations:
string joined = list.Aggregate(new StringBuilder(),
(sb, s) => sb.Append(s).Append(';'),
sb => (sb.Length > 0) ? sb.ToString(0, sb.Length - 1)
: "");
You can do it using below code
list.Aggregate((i, j) => i + ";" + j);
You'll need to provide an initializer, otherwise the first element will not have a ; added to it:
list.Aggregate<String>("", (x,y) => x + String.Format("{0};",y));

NOLOCK with Linq to SQL

Is it possible to get Linq2Sql to emit a NOLOCK in its SQL? And if so, how?
Yes it is, so here's the entry from my blog:
The NOLOCK hint is essentially the
same as wrapping a query in a
transaction whose "isolation level" is
set to "read uncommitted". It means
that the query doesn't care if stuff
is in the process of being written to
the rows it's reading from - it'll
read that "dirty" data and return it
as part of the result set.
Turns out that you can do the whole
"read uncommitted" transaction thing
using the old System.Transactions
namespace introduced in .NET 2.0.
Here's some sample code:
using (var txn = new TransactionScope(
TransactionScopeOption.Required,
new TransactionOptions
{
IsolationLevel = IsolationLevel.ReadUncommitted
}
))
{
// Your LINQ to SQL query goes here
}
So I'm creating a new TransactionScope
object and telling it to use a
read-uncommitted isolation level. The
query within the "using" statement now
acts as if all its tables were reading
with the NOLOCK hint.
Here are the first results from a Google search for "linq sql nolock":
InfoQ: Implementing NOLOCK with LINQ to SQL and LINQ to Entities
Matt Hamilton - LINQ to SQL and NOLOCK Hints : Mad Props!
Scott Hanselman's Computer Zen - Getting LINQ to SQL and LINQ to ...
Further to theKing's LinqPad My Extensions addition:
public static IQueryable<T> DumpNoLock<T>(this IQueryable<T> query)
{
using (var txn = GetNewReadUncommittedScope())
{
return query.Dump();
}
}
public static System.Transactions.TransactionScope GetNewReadUncommittedScope()
{
return new System.Transactions.TransactionScope(
System.Transactions.TransactionScopeOption.RequiresNew,
new System.Transactions.TransactionOptions
{
IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted
});
}
public static IQueryable<T> DumpNoLock<T>(this IQueryable<T> query, string description)
{
using (var txn = GetNewReadUncommittedScope())
{
return query.Dump(description);
}
}
public static List<T> ToListNoLock<T>(this IQueryable<T> query)
{
using (var txn = GetNewReadUncommittedScope())
{
return query.ToList();
}
}
public static U NoLock<T,U>(this IQueryable<T> query, Func<IQueryable<T>,U> expr)
{
using (var txn = GetNewReadUncommittedScope())
{
return expr(query);
}
}
The last one means you can do a NOLOCK on any evaluating queries you haven't a NoLock explicitly written for (like I've got for ToListNoLock above). So, for example:
somequery.NoLock((x)=>x.Count()).Dump();
will evaluate the query with NOLOCK.
Note that you have to ensure you're evaluating the query. E.g. .NoLock((x)=>x.Distinct()).Count().Dump() won't do anything usefully different from .Distinct().Count().Dump().
A simple way may be to run a command on your DataContext class
using (var dataContext = new DataContext())
{
dataContext.ExecuteCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED");
// Your SQL query
}
Here is an extension method to use with LINQPAD
public static IQueryable<T> Dump2<T>(this IQueryable<T> query)
{
using (var txn = new System.Transactions.TransactionScope(TransactionScopeOption.RequiresNew,
new TransactionOptions
{
IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted
}))
{
return query.Dump();
}
}
Then you can call it as:
MyTable.Where(t => t.Title = "Blah").Dump2();
In my case, Entity Framework 5 (based on #Soppus answer):
private FoobarEntities db = new FoobarEntities();
public FoobarController()
{
db.Database.ExecuteSqlCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED");
}