I would like to run a LINQ query like this:
var words = from p in db.Words
where p.Document.Corpus.Name == corpus
//where LevenshteinDistance(p.Text.ToCharArray(), word.ToCharArray()) < threshold
select p;
But if I place the "LevenshteinDistance" function in there it will generate an error:
NotSupportedException: Method 'Char[] ToCharArray()' has no supported translation to SQL.
Is there a correct way to do this?
LINQ to SQL tries to translate the entire expression into SQL. If you want to run your distance function on SQL Server, you'll need to define a SQL Server UDF and map a custom CLR method to that. If you're content to get all the results and then filter client-side on the distance function, use AsEnumerable():
var words = (from p in db.Words
where p.Document.Corpus.Name == corpus)
select p)
.AsEnumerable()
.Where(p => /* distance function */ < threshold);
The AsEnumerable forces LINQ to SQL to enumerate the query results, allowing the remainder of the query to be resolved using LINQ to Objects and your distance delegate (instead of being translated to SQL).
Related
I have a LINQ query which I'm using to select some rows out of a SQL database. Each row from my database represents a footprint of physical space, and I'm trying to select just the rows which contain a given point. The part of the query that is giving me issues is below:
LinqMetaData meta = new LinqMetaData(da);
var captures = (from c in meta.Capture
where
(c.TLLat.HasValue && lat < Math.Max(Math.Max(c.BLLat.Value, c.BRLat.Value), Math.Max(c.TLLat.Value, c.TRLat.Value)))
&&
(c.TLLat.HasValue && lat > Math.Min(Math.Min(c.BLLat.Value, c.BRLat.Value), Math.Min(c.TLLat.Value, c.TRLat.Value)))
select c);
When I run the code, I get this error:
The binary expression '(39.3237282094724 <
Max(Max(EntityField(LPLA_1.BLLat AS BLLat), EntityField(LPLA_1.BRLat
AS BRLat)), Max(EntityField(LPLA_1.TLLat AS TLLat),
EntityField(LPLA_1.TRLat AS TRLat))))' can't be converted to a
predicate expression.
I've assumed this means I can't use Math.Max() / Math.Min() in a LINQ query...Is this correct?
EDIT:
I am using LinqMetaData for my query, which comes from the LLBLGen Pro c# library. I think that this implementation of LINQ may not support Math.Max() / Math.Min() within its queries.
Simply move Max and Min calculations outside of your query as separate variables.
Not only that could affect your query overall performance but will remove the error you are seeing which is in this case connected to the provider unable to translate nested Max and Min methods.
Here is a Microsoft Documentation about some of the known issues with LINQ to Entities.
Another approach would be to convert the above query to pure SQL Procedure.
I have an Expression that converts one type of object to another type. The expression is as follows:
public Expression<Func<SQLRepository.ActionType, Model.ActionType>> DBActionTypeToActionType =
(SQLRepository.ActionType at) => new Model.ActionType()
{
ID = at.OID,
DisplayName = at.DisplayName
};
I can use the Expression like this:
var linq = (from at in dc.SQLRepositoryDC.ActionTypes select at).Select(DBActionTypeToActionType);
But I'd like to use it like this:
var linq = (from at in dc.SQLRepositoryDC.ActionTypes select DBActionTypeToActionType.Compile().Invoke(at));
I've been looking for a couple days now and I can only find references to doing this in the Where clause. It seems that if I'm able to use the function calls to do this, it should be possible using the query syntax.
The reason it is important to do use the query syntax is that some of the objects that are being selected are composed of many sub-objects and trying to chain them all of the conversions together with the function notation will be much harder to write and maintain.
It seems that if I'm able to use the function calls to do this, it should be possible using the query syntax.
That's not true. Query notation always goes via a lambda expression. For example
from x in y select z
ends up as
y.Select(x => z)
That means if you've already got an expression tree that you want to pass directly as the argument to Select, you can't use query expressions because there's this extra level of indirection.
Now the options available depend on where you need to apply the predefined expression. You can always use it in the source, and then continue with the query:
var query = from foo in dc.ActionTypes.Select(DBActionTypeToActionType)
where foo.Stuff
select foo.Other;
Or using it at the end is easy:
var query = (from bar in dc.ActionTypes
where bar.Stuff
select bar).Select(DBActionTypeToActionType);
Does that help at all?
I know this was partly asked before, but none of the questions completely answer this.
What happens when one uses LINQ to SQL to retrieve data from the database?
I've read the following questions:
Optimizing a LINQ to SQL query
Linq-To-Sql optimization for queries
What is unclear to me is: at which point is the database accessed? When are the queries run?
If I run the following query, how will it translate to a SQL query?
DatabaseDataContext db = new DatabaseDataContext();
var users = from x in db.Users
where x.Rank > 10
orderby x.RegistrationDate descending
select x)
.Skip(pageIndex * recordCount)
.Take(recordCount);
And then, later, if I try to access some property of some user, how will the query be constructed (this is partly answered here)?
var temp = users.ToList()[0].SomeProperty;
Basically, what I really want to know is how the LINQ to SQL works under the hood, how it goes from the C# language statement to the SQL and how it is optimized.
The LINQ to SQL framework will take your Linq query, which is in fact an expression tree, and then will convert this expression tree into a pure SQL query. See How to: Use Expression Trees to Build Dynamic Queries
In fact, every expression tree can be translated into whatever langage or database you need. You will have different providers implementing IQueryable for different databases (Oracle, SQLite, etc.). Note that LINQ to SQL is the abbreviation of LINQ to SQL Server. On the other hand, Entity framework/LINQ to Entities can be extent more easily for other databases.
The main point here is the IQueryable interface, which contains an expression tree, and also the implementation of the provider. For an example on how to implement a provider, ie how to translate from an expression tree to a query, see LINQ: Building an IQueryable Provider
Here is a snippet that will give you a flavor of what happens under the hood:
if (select.OrderBy != null && select.OrderBy.Count > 0)
{
this.AppendNewLine(Indentation.Same);
sb.Append("ORDER BY ");
for (int i = 0, n = select.OrderBy.Count; i < n; i++)
{
OrderExpression exp = select.OrderBy[i];
if (i > 0)
{
sb.Append(", ");
}
this.Visit(exp.Expression);
if (exp.OrderType != OrderType.Ascending)
{
sb.Append(" DESC");
}
}
}
The queries are run as soon as you demand the result.
var qry = (from x in db.Users where x.Rank > 10 orderby x.RegistrationDate descending
select x)
at this point the query has not run, becuase you haven't used the result.
Put it in a foreach or transfor it to a List and the query is forced to Materiliaze.
The rule of thumb is:
Whenever GetEnumerator is called on an IQueryable - the query is forced to materiliaze (wich meens "to to the database and get the actual recourds")
All you want to know is answered in the article on MSDN about LINQ to SQL: http://msdn.microsoft.com/en-us/library/bb425822.aspx
By the way, if you're only going to use a part of your result, as in your code above, it's better to modify your query, like so:
var prop = (from x in db.Users
where x.Rank > 10
orderby x.RegistrationDate descending
select x.SomeProperty)
.Skip(pageIndex)
.First()
.Select(x => x);
Optimization you do in your query is often more important than how the system performs peephole optimization under the hood...
Is it possible to use custom method In query for example:
var result = from u in context.MyTable where MyMethod(u) == 10 select u;
As Pranay explains, you cannot have a custom (C#) method as part of the LINQ to SQL query, because LINQ to SQL wouldn't be able to look at the expression tree of the method and so it cannot translate it to SQL.
One option that you have is to write your function in SQL and store it as a SQL function on the SQL Server (possibly, you could also use SQL CLR, but I have not tried that). Then you can add the function to your DataContext type and LINQ to SQL will translate it to calls to the function on SQL server. Something like:
var result = from u in context.MyTable
where context.MyMethod(u) == 10 select u;
The problem, of course, is that you'll need to write the function in SQL (I think SQL CLR could also work - not sure about the performance and other possible complications though)
I also wrote an article (some time ago) that shows how to do this when you write the "method" as an expression tree way (as a value of type Expression<Func<...>>), which is possible, because in this case, the code is compiled as an expression tree. However, there is some postprocessing that has to be done and you can still write just a single expression that can be easily inlined in the LINQ query.
Check this full article : What is and what isn't possible with linq
Following is not possible
// function used in filter
static bool MyFunc(Nwind.Product p)
{
return p.ProductName.StartsWith("B");
}
// query that uses MyFunc
var q =
from p in db.Products
where MyPriceFunc(p.UnitPrice) > 30m
select p
It compiles with no errors, but when you execute it LINQ to SQL throws an exception saying: "Static method System.Boolean MyTest(LINQTest.Nwind.Product) has no supported translation to SQL."
The exception is actually thrown when you try to fetch results from q (for example using the foreach statement), because LINQ to SQL attempts to convert the expression trees to T-SQL only when the results are needed and the query must be executed.
To fix the example you can simply copy the code that checks whether product name starts with "B" to the where clause of the query and it would work fine.
Yes, but if you are using Linq-to-Sql - your method has to have special code to handle to SQL conversion.
I have an Expression that converts one type of object to another type. The expression is as follows:
public Expression<Func<SQLRepository.ActionType, Model.ActionType>> DBActionTypeToActionType =
(SQLRepository.ActionType at) => new Model.ActionType()
{
ID = at.OID,
DisplayName = at.DisplayName
};
I can use the Expression like this:
var linq = (from at in dc.SQLRepositoryDC.ActionTypes select at).Select(DBActionTypeToActionType);
But I'd like to use it like this:
var linq = (from at in dc.SQLRepositoryDC.ActionTypes select DBActionTypeToActionType.Compile().Invoke(at));
I've been looking for a couple days now and I can only find references to doing this in the Where clause. It seems that if I'm able to use the function calls to do this, it should be possible using the query syntax.
The reason it is important to do use the query syntax is that some of the objects that are being selected are composed of many sub-objects and trying to chain them all of the conversions together with the function notation will be much harder to write and maintain.
It seems that if I'm able to use the function calls to do this, it should be possible using the query syntax.
That's not true. Query notation always goes via a lambda expression. For example
from x in y select z
ends up as
y.Select(x => z)
That means if you've already got an expression tree that you want to pass directly as the argument to Select, you can't use query expressions because there's this extra level of indirection.
Now the options available depend on where you need to apply the predefined expression. You can always use it in the source, and then continue with the query:
var query = from foo in dc.ActionTypes.Select(DBActionTypeToActionType)
where foo.Stuff
select foo.Other;
Or using it at the end is easy:
var query = (from bar in dc.ActionTypes
where bar.Stuff
select bar).Select(DBActionTypeToActionType);
Does that help at all?