Why does this throw System.NotSupportedException?
string foo(string f) { return f; }
string bar = "";
var item = (from f in myEntities.Beer
where f.BeerName == foo(bar)
select f).FirstOrDefault();
Edit: Here's an MSDN reference that (kind of) explains things...
Any method calls in a LINQ to Entities
query that are not explicitly mapped
to a canonical function will result in
a runtime NotSupportedException
exception being thrown. For a list of
CLR methods that are mapped to
canonical functions, see CLR Method to
Canonical Function Mapping.
See also http://mosesofegypt.net/post/LINQ-to-Entities-what-is-not-supported.aspx
EDIT: Okay, the code blows up because it doesn't know what to do with the call to foo(). The query is built up as an expression tree which is then converted to SQL.
The expression tree translator knows about various things - such as string equality, and various other methods (e.g. string.StartsWith) but it doesn't know what your foo method does - foo() is a black box as far as it's concerned. It therefore can't translate it into SQL.
The second version will fail as soon as you try to iterate over it. You can't use a locally defined method in an IQueryable<> where clause (of course, you can, but it will fail when the LINQ provider tries to translate it into SQL).
Because in the 2nd query no actual query is executed. Try adding ToList() where SingleOrDefault() is.
It's probably because the SQL-generation functionality isn't able to determine what to do with your foo() function, so can't generate output for it.
Related
I am trying to achieve a simple task, and I don't find a way to do it. I am trying to convert a LINQ result to a list of objects. I am following the syntax posted in this accepted SO answer.. Here is my code:
var LinqHallazgos = (from RA_Hallazgos in context.RA_Hallazgos
select new
{
HallazgoId = RA_Hallazgos.HallazgoId,
Hallazgo = RA_Hallazgos.Hallazgo
});
List<RA_Hallazgos> Hallazgos = LinqHallazgos.ToList<RA_Hallazgos>();
And this is the error that I get:
It says that "LinqHallazgos", which is an iqueryable, doesn't contain a definition for ToList. But I see the "ToList" method in intellisense. It also says that it expect an IEnumerable but this answer seems to use similar syntax.
What I am doing wrong and how in the world I get the LINQ result as a list of a particular object??
You are making this too complex. It seems all you want to do is materialize the DbSet<RA_Hallazgos> to memory (retrieve the content from the database). If that is the case just use the ToList() linq extension on the DbSet and you are done. Note that it will retrieve everything as you did not specify a filter (ie. any limiting predicates like Where / Take / Skip / etc).
List<RA_Hallazgos> Hallazgos = context.RA_Hallazgos.ToList();
Just call .ToList(). You have an anonymous type there (the new {}) so you can't specify the type explicitly even if you wanted to.
Otherwise, if RA_Hallazgos is an actual type, use new RA_Hallazgos{} to avoid creating an anonymous type.
Try
select new RA_Hallazgos
{
HallazgoId = RA_Hallazgos.HallazgoId,
Hallazgo = RA_Hallazgos.Hallazgo
}
List<RA_Hallazgos> Hallazgos = LinqHallazgos.ToList()();
I know from the MSDN's article about How to: Modify Expression Trees what an ExpressionVisitor is supposed to do. It should modify expressions.
Their example is however pretty unrealistic so I was wondering why would I need it? Could you name some real-world cases where it would make sense to modify an expression tree? Or, why does it have to be modified at all? From what to what?
It has also many overloads for visiting all kinds of expressions. How do I know when I should use any of them and what should they return? I saw people using VisitParameter and returning base.VisitParameter(node) the other on the other hand were returning Expression.Parameter(..).
There was a issue where on the database we had fields which contained 0 or 1 (numeric), and we wanted to use bools on the application.
The solution was to create a "Flag" object, which contained the 0 or 1 and had a conversion to bool. We used it like a bool through all the application, but when we used it in a .Where() clause the EntityFramework complained that it is unable to call the conversion method.
So we used a expression visitor to change all property accesses like .Where(x => x.Property) to .Where(x => x.Property.Value == 1) just before sending the tree to EF.
Could you name some real-world cases where it would make sense to modify an expression tree?
Strictly speaking, we never modify an expression tree, as they are immutable (as seen from the outside, at least, there's no promise that it doesn't internally memoise values or otherwise have mutable private state). It's precisely because they are immutable and hence we can't just change a node that the visitor pattern makes a lot of sense if we want to create a new expression tree that is based on the one we have but different in some particular way (the closest thing we have to modifying an immutable object).
We can find a few within Linq itself.
In many ways the simplest Linq provider is the linq-to-objects provider that works on enumerable objects in memory.
When it receives enumerables directly as IEnumerable<T> objects it's pretty straight-forward in that most programmers could write an unoptimised version of most of the methods pretty quickly. E.g. Where is just:
foreach (T item in source)
if (pred(item))
yield return item;
And so on. But what about EnumerableQueryable implementing the IQueryable<T> versions? Since the EnumerableQueryable wraps an IEnumerable<T> we could do the desired operation on the one or more enumerable objects involved, but we have an expression describing that operation in terms of IQueryable<T> and other expressions for selectors, predicates, etc, where what we need is a description of that operation in terms of IEnumerable<T> and delegates for selectors, predicates, etc.
System.Linq.EnumerableRewriter is an implementation of ExpressionVisitor does exactly such a re-write, and the result can then simply be compiled and executed.
Within System.Linq.Expressions itself there are a few implementations of ExpressionVisitor for different purposes. One example is that the interpreter form of compilation can't handle hoisted variables in quoted expressions directly, so it uses a visitor to rewrite it into working on indices into a a dictionary.
As well as producing another expression, an ExpressionVisitor can produce another result. Again System.Linq.Expressions has internal examples itself, with debug strings and ToString() for many expression types working by visiting the expression in question.
This can (though it doesn't have to be) be the approach used by a database-querying linq provider to turn an expression into a SQL query.
How do I know when I should use any of them and what should they return?
The default implementation of these methods will:
If the expression can have no child expressions (e.g. the result of Expression.Constant()) then it will return the node back again.
Otherwise visit all the child expressions, and then call Update on the expression in question, passing the results back. Update in turn will either return a new node of the same type with the new children, or return the same node back again if the children weren't changed.
As such, if you don't know you need to explicitly operate on a node for whatever your purposes are, then you probably don't need to change it. It also means that Update is a convenient way to get a new version of a node for a partial change. But just what "whatever your purposes are" means of course depends on the use case. The most common cases are probably go to one extreme or the other, with either just one or two expression types needing an override, or all or nearly all needing it.
(One caveat is if you are examining the children of those nodes that have children in a ReadOnlyCollection such as BlockExpression for both its steps and variables or TryExpression for its catch-blocks, and you will only sometimes change those children then if you haven't changed you are best to check for this yourself as a flaw [recently fixed, but not in any released version yet] means that if you pass the same children to Update in a different collection to the original ReadOnlyCollection then a new expression is created needlessly which has effects further up the tree. This is normally harmless, but it wastes time and memory).
The ExpressionVisitor enables the visitor pattern for Expression's.
Conceptually, the problem is that when you navigate an Expression tree, all you know is that any given node is an Expression, but you don't know specifically what kind of Expression. This pattern allows you to know what kind of Expression you're working with and specify type-specific handling for different kinds.
When you have an Expression, you can just call .Modify. The Expression knows its own type, so it'll call back the appropriate override.
Looking at the MSDN example you linked:
public class AndAlsoModifier : ExpressionVisitor
{
public Expression Modify(Expression expression)
{
return Visit(expression);
}
protected override Expression VisitBinary(BinaryExpression b)
{
if (b.NodeType == ExpressionType.AndAlso)
{
Expression left = this.Visit(b.Left);
Expression right = this.Visit(b.Right);
// Make this binary expression an OrElse operation instead of an AndAlso operation.
return Expression.MakeBinary(ExpressionType.OrElse, left, right, b.IsLiftedToNull, b.Method);
}
return base.VisitBinary(b);
}
}
In this example, if the Expression happens to be a BinaryExpression, it'll call back VisitBinary(BinaryExpression b) given in the example. Now, you can deal with that BinaryExpression knowing that it's a BinaryExpression. You could also specify other override methods that handle other kinds of Expression's.
It's worth noting that, since this is an overloaded resolution trick, visited Expression's will call back the best-fitting method. So, if there're different kinds of BinaryExpression's, then you could write an override for one specific subtype; if another subtype calls back, it'll just use the default BinaryExpression handling.
In short, this pattern allows you to navigate an Expression tree knowing what kind of Expression's you're working with.
Specific real world example I have just encountered occurred when shifting to EF Core and migrating from Sql Server (MS Specific) to SqlLite (platform independent).
The existing business logic revolved around a middle tier/ service layer interface that assumed Full Text Search (FTS) happened auto-magically in the background which it does with SQL Server. Search related queries were passed into this tier via Expressions and FTS against an Sql Server store required no additional FTS specific entities.
I didn't want to change any of this but with SqlLite you have to target a specific virtual table for a Full Text Search which would in turn have meant changing all the middle tier calls to re-target the FTS tables/entities and then joining them to the business entity tables to get a similar result set.
But by sub-classing ExpressionVisitor I was able to intercept the calls in the DAL layer and simply rewrite the incoming expression (or more precisely some of the BinaryExpressions within the overall search expression) to specifically handle SqlLites FTS requirements.
This meant that specialization of the datalayer to the data store happened within a single class that was called from a single place within a repository base class. No other aspects of the application needed to be altered in order to support FTS via EFCore and any SqlLite FTS related entities could be contained in a single pluggable assembly.
So ExpressionVisitor is really very useful, especially when combined with the whole notion of being able to pass around expression trees as data via various forms of IPC.
I developed the extension method:
public static IQueryable<T> Get<T>(this DataContext dataContext) where T : class
{
return dataContext.GetTable<T>();
}
Then I tried to use it:
dataContext.Get<XDbCurrency>().
Where(c => c.Id == XCurrencyId.USD).
SelectMany(
c =>
dataContext.Get<XDbCurrencyRate>().
Where(cr =>
cr.CurrencyId == c.Id &&
cr.StartOn <= DateTime.UtcNow &&
cr.EndOn > DateTime.UtcNow).
Take(1),
(c, cr) => cr).
ToArray();
I get the exception Member access 'XCurrencyId CurrencyId' of 'X.XDbCurrencyRate' not legal on type 'System.Data.Linq.Table``1[X.XDbCurrencyRate]. When I change Get back to GetTable - everything works! When I change the return type of Get from IQueryable<T> to Table<T> - it crashes.
UPDATE. I created XDataContextBase class, moved Get method there, inherited DBML-generated XDataContext from XDataContextBase - unfortunately it does not help. Magic!!
UPDATE. this.GetTable<XDbCurrencyRate> works, this.XDbCurrencyRates works, this.Get<XDbCurrencyRate> not works either Get is extension method or method in base class. By the way, internally this.XDbCurrencyRates is implemented absolutely like my Get. Magic!!
UPDATE. Looks like Linq-to-SQL supports only two things: either direct call of DataContext.GetTable<> or call of any-named property that returns System.Data.Linq.Table<XDbCurrencyRate>. If I create System.Data.Linq.Table<XDbCurrencyRate> Foo - it works, but when I create IQueryable<XDbCurrencyRate> Foo - it crashes with Queries with local collections are not supported.. Magic!!
Any ideas?
This is because the initial Get call is not part of the query tree. Just a normal method call. The second call is embedded in the tree and LINQ to SQL has no idea what that method means.
I know that EF would give up here immediately. I believe L2S is basically capable of running such a method locally and trying to inline the query that it returns. Here, that seems to now work out (or I'm wrong about that).
What I did was to create a custom LINQ provider that rewrites expression trees to execute such methods locally, inline their results into the query tree and then forward to LINQ to SQL. This is not trivial.
Maybe you can make AsExpandable from the so called "LINQ kit" (approximate spelling) work.
I'm trying to get the query string with parameters for debugging purposes from entity framework. No, I will not use EFProfiler because the query strings need to be visible as an output on the page. Most of those queries are written manually, using ExecuteStoredQuery(). However, casting them to ObjectQuery yields null.
Example:
ObjectResult<Parent> model = _context.ObjectContext().ExecuteStoreQuery<Parent>("SELECT * FROM Parents");
var objectQuery = model.AsQueryable() as ObjectQuery<Parent>;
objectQuery is null. ObjectContext() is a simple method in the datacontext that looks like:
return (this as IObjectContextAdapter).ObjectContext;
I have exhausted my own ideas and anything that is yielded back from searches is... well, useless, because nobody seems to get that problem. Mind, the results come back correctly from the query.
Edit: Right, I should have mentioned this, as well.
Doing this:
var oq = m as ObjectQuery<Parent>;
Yields me this:
Cannot convert type 'System.Data.Objects.ObjectResult' to 'System.Data.Objects.ObjectQuery' via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion
Whence is when I thought it needed to be cast AsQueryable(), which, well... is null, for obvious reasons. It was my tired head that forgot to add this little detail.
I think the other anwers made clear that you can't cast an ObjectResult<T> to an ObjectQuery<T>. But I'm interested in your comment
I tried CreateQuery and I ran into problems with it. For one, it doesn't like when the user tries to SELECT *, you seem to have to specify all the fields you need to get.
You can use an ObjectQuery to do a "*" search:
ObjectContext().ObjectQuery<Parent>("SELECT VALUE par FROM Parents AS par")
As you see, there is no actual * in the query string and the trace string doesn't have a * but shows all fields. But you don't have to specify all field to build the query string. I hope this will help you to make better use of ObjectQuery.
Your cast as ObjectQuery<Parent> is not correct, cause ObjectResult<Parent>.AsQueryable() will return an IQueryable<Parent> that is not of type ObjectQuery<Parent>.
AsQueryable is the extension method of the class Queryable that converts an IEnumerable to an IQueryable.
The result is that your variable objectQuery is null.
Surely you ACTUALLY want to use CreateQuery(sql) rather than ExecuteStoreQuery(sql).
Given the name, ExecuteStoreQuery actually runs the SQL, whilst CreateQuery returns an ObjectQuery ready to be sent to the database.
Obviously you can then call Execute on ObjectQuery to return the ObjectResult
I have written a custom IQueryProvider class that takes an expression and analyses it against a SQL database (I know I could use Linq2Sql but there are some modifications and tweaks that I need that unfortunately make Linq2Sql unsuitable). The class will identify and do something with the properties that are marked (using attributes) but any that aren't I would like to be able to pass the expression on to a LinqToObject provider and allow it to filter the results after.
For example, suppose I have the following linq expression:
var parents=Context.Parents
.Where(parent=>parent.Name.Contains("T") && parent.Age>18);
The Parents class is a custom class that implements IQueryProvider and IQueryable interfaces, but only the Age property is marked for retrieval, so the Age property will be processed, but the Name property is ignored because it is not marked. After I've finished processing the Age property, I'd like to pass the whole expression to LinqToObjects to process and filter, but I don't know how.
N.B. It doesn't need to remove the Age clause of the expression because the result will be the same even after I've processed it so I will always be able to send the whole expression on to LinqToObjects.
I've tried the following code but it doesn't seem to work:
IEnumerator IEnumerable.GetEnumerator() {
if(this.expression != null && !this.isEnumerating) {
this.isEnumerating = true;
var queryable=this.ToList().AsQueryable();
var query = queryable.Provider.CreateQuery(this.expression);
return query.GetEnumerator();
}
return this;
}
this.isEnumerating is just a boolean flag set to prevent recursion.
this.expression contains the following:
{value(namespace.Parents`1[namespace.Child]).Where(parent => ((parent.Name.EndsWith("T") AndAlso parent.Name.StartsWith("M")) AndAlso (parent.Test > 0)))}
When I step through the code, despite converting the results to a list, it still uses my custom class for the query. So I figured that because the class Parent was at the beginning of the expression, it was still routing the query back to my provider, so I tried setting this.expression to Argument[1] of the method call so it was as such:
{parent => ((parent.Name.EndsWith("T") AndAlso parent.Name.StartsWith("M")) AndAlso (parent.Test > 0))}
Which to me looks more like it, however, whenever I pass this into the CreateQuery function, I get this error 'Argument expression is not valid'.
The node type of the expression is now 'Quote' though and not 'Call' and the method is null. I suspect that I just need to make this expression a call expression somehow and it will work, but I'm not sure how to.
Please bear in mind that this expression is a where clause, but it may be any kind of expression and I'd prefer not to be trying to analyse the expression to see what type it is before passing it in to the List query provider.
Perhaps there is a way of stripping off or replacing the Parent class of the original expression with the list provider class but still leaving it in a state that can just be passed in as expression into the List provider regardless of the type of expression?
Any help on this would be greatly appreciated!
You were so close!
My goal was to avoid having to "replicate" the full mind-numbingly convoluted SQL-to-Object expressions feature set. And you put me on the right track (thanks!) here's how to piggy-back SQL-to-Object in a custom IQueryable:
public IEnumerator<T> GetEnumerator() {
// For my case (a custom object-oriented database engine) I still
// have an IQueryProvider which builds a "subset" of objects each populated
// with only "required" fields, as extracted from the expression. IDs,
// dates, particular strings, what have you. This is "cheap" because it
// has an indexing system as well.
var en = ((IEnumerable<T>)this.provider.Execute(this.expression));
// Copy your internal objects into a list.
var ar = new List<T>(en);
var queryable = ar.AsQueryable<T>();
// This is where we went wrong:
// queryable.Provider.CreateQuery(this.expression);
// We can't re-reference the original expression because it will loop
// right back on our custom IQueryable<>. Instead, swap out the first
// argument with the List's queryable:
var mc = (MethodCallExpression)this.expression;
var exp = Expression.Call(mc.Method,
Expression.Constant(queryable),
mc.Arguments[1]);
// Now the CLR can do all of the heavy lifting
var query = queryable.Provider.CreateQuery<T>(exp);
return query.GetEnumerator();
}
Can't believe this took me 3 days to figure out how to avoid reinventing wheel on LINQ-to-Object queries.