I m using ...
tmpLst = (from e in App.lstAllChilds where e.Id == Id select e).ToList();
where lstAllChilds is the list, which contains some corrupted data as well.
So now i m tying to handle Try-Catch block inside this query.
Please help.
In case if you just want to ignore "bad elements" then:
App.lstAllChilds.SkipExceptions().Where( e => e.Id == Id).ToList();
Extension method:
public static class Extensions
{
public static IEnumerable<T> SkipExceptions<T>(this IEnumerable<T> values)
{
using (var enumerator = values.GetEnumerator())
{
bool next = true;
while (next)
{
try
{
next = enumerator.MoveNext();
}
catch
{
continue;
}
if (next) yield return enumerator.Current;
}
}
}
}
Here is the simplest change you can make to simply exclude items which are null or are raising an exception.
tmpLst = App.lstAllChilds.Where(e =>
{
try
{
return e != null && e.Id == Id;
}
catch
{
return false;
}
}).ToList();
But in my opinion you probably should investigate and solve the underlying problem. This doesn't seem like a scenario where exceptions should be expected.
So, here's the thing. There's language integrated query (Linq), and then there's yielded enumeration (a.k.a. Iterators).
Linq allows you to define an expression tree that is later executed by something that may or may not be C# (for example the expression could be translated into a SQL query). If you're writing linq there is a good chance your query provider (the thing that does the expression translation) does not support exception handling (much less whatever you're doing that throws exceptions).
Interators on the other hand (or "linq to objects") just ends up executing in C#, so you can just go wild with your exception handling.
For example w/ linq to objects you can do this:
var myList = new[] { "1", "2", "BARF", "3" };
var sum = myList.Select(str => {
try {
return Int32.Parse(str);
} catch {
return 0;
}
}).Aggregate((x, y) => x + y);
If you're indeed doing linq to objects, and you just want to skip elements where your source IEnumerable threw an exception check out Vladimir Gondarev's answer.
The important thing to understand however, is that the anonymous function we just passed to that Select call is not an Expression (an uncompiled expression tree), it is a Func (a delegate pointing to compiled c# code), which means that it will run in the .Net process, even if we replaced myList with a linq to entities table (or some other linq provider). The reason for this is that the C# expression syntax does not support blocks, nor does it support try-catch. Unsurprisingly, given that, the SQL-style Linq statements (from xxx select yyy) also do not support try-catch blocks.
However, just because the C# expression syntax doesn't support it doesn't mean you can't do it. But, to be clear, I do not recommend doing this because I highly doubt there is a QueryProvider in existence that supports it (aside from the linq to objects provider). For the curious here's how you would create a lambda expression that contains a try-catch block.
var parseMethod = typeof(Int32).GetMethod("Parse", new[] { typeof(String) });
var param = Expression.Parameter(typeof(String));
var selectExp =
Expression.Lambda<Func<String, Int32>>(
Expression.TryCatch(
Expression.Call(parseMethod, param),
Expression.Catch(typeof(Exception), Expression.Constant(0))
),
param
);
var sum = myList.Select(selectExp).Aggregate((x, y) => x + y);
So when somebody implements a QueryProvider backed by a store that supports exception handling, you could use this.
It depends what exactly you are trying to achieve:
Return the list except "broken" items.
You can try using a Where clause to check and filter them out:
App.lstAllChilds.Where(x => IsValidNode(x, Id)).ToList();
Apparently you need to implement IsValidNode which should check for null, if it can throw an InvalidObjectException (not sure if you can easily detect it but you can always wrap it in a try-catch block) and Id equality. Like that:
private bool IsValidNode(Child c, int id)
{
if (x == null) return false;
try {
return c.Id == id;
}
catch (InvalidObjectException)
{
}
return false;
}
Return an empty list if there are any broken items.
Just wrap the entire thing in a try-catch block
Related
In our application we want to have standard methods for various conditions in our database. For instance, we have different types of transactions, and we want to create standard methods for retrieving them within other queries. However, this gives us the error:
Method '' has no supported translation to SQL
The method might look like this:
public static bool IsDividend(this TransactionLog tl)
{
return tl.SourceTypeID == (int)JobType.Dividend || tl.SourceTypeID == (int)JobType.DividendAcct;
}
To be used as such:
var dividends = ctx.TransactionLogs.Where(x => x.IsDividend());
Of course, if I copy the logic from IsDividend() into the Where clause, this works fine, but I end up duplicating this logic many places and is hard to track down if that logic changes.
I think if I would convert this to an expression like this it would work, but this is not as preferable a setup as being able to use methods:
public Expression<Func<TransactionLog, bool>> IsDividend = tl => tl.SourceTypeID == (int)JobType.Dividend || tl.SourceTypeID == (int)JobType.DividendAcct;
var dividends = ctx.TransactionLogs.Where(IsDividend);
Is there a way to force Linq to evaluate the method as an expression? Or to "transform" the method call into an expression within a linq query? Something like this:
var dividends = ctx.TransactionLogs.Where(tl => ToExpression(tl.IsDividend));
We are using Linq-to-SQL in our application.
Well having static property containing the expressions seems fine to me.
The only way to make it work with Methods would be to create a method which returns this expression, and then call it inside where:
public class TransactionLog
{
Expression<Func<TransactionLog, bool>> IsDividend() {
Expression<Func<TransactionLog, bool>> expression = tl => tl.SourceTypeID == (int)JobType.Dividend || tl.SourceTypeID == (int)JobType.DividendAcct;
return expression;
}
}
public class TransactionLogExtension
{
Expression<Func<TransactionLog, bool>> IsDividend(this TransactionLog log) {
Expression<Func<TransactionLog, bool>> expression = tl => tl.SourceTypeID == (int)JobType.Dividend || tl.SourceTypeID == (int)JobType.DividendAcct;
return expression;
}
}
and use it via
var dividends = ctx.TransactionLogs.Where(TransactionLog.IsDividend());
or as extension method
var dividends = ctx.TransactionLogs.Where(x.IsDividend());
But none of it is will work with var dividends = ctx.TransactionLogs.Where(x => x.IsDividend()); because x => x.IsDividend(); itself is an expression tree and your database provider can't translate "IsDividend" into an SQL statement.
But the other two options will at least allow you to pass in parameters (which doesn't work if you store the Expressions as instance or static properties).
I think that LINQ to SQL doesn't fully supports even common and build-in functions. (At least EF does not do it). And moreover - when it deals with user defined methods. I predict that your variant with expression will fall as well as the variant with method call unless you call it after enumeration (ToList or similar method). I suggest to keep the balance between 1) stored procedures at server, 2) common conditions hardcoded in Where clauses in C#, 3) expression trees generation in C#. All these points are relatively complex, for sure (and to my mind there is no easy and general solution).
Try using Extension Methods, like so:
public static class TransactionLogExtensions {
public static IQueryable<TransactionLog> OnlyDividends(this IQueryable<TransactionLog> tl)
{
return tl.Where(t=>t.SourceTypeID == (int)JobType.Dividend || t.SourceTypeID == (int)JobType.DividendAcct);
}
}
Call it like so:
var dividends=db.TransactionLogs.OnlyDividends();
or
var dividends=db.TransactionLogs.OnlyDividends().OrderBy(...);
For this scenario you can use Func. Linq works very good with those.
Here is the simple example of using Func in Linq query. Feel free to modify and use.
Func<int,bool> isDivident = x => 3==x;
int[] values = { 3, 7, 10 };
var result = values.Select (isDivident );
Working with DB through DataContext.
Have such operation:
var flat = StavRealtyDb.TargetFlat
.Where(x => true || _some condition_).ToList();
So, if the FIRST part of condition is true, the SECOND part should be skipped by compiler, right?
But it doesn't happens. The same problem will happen, if there would be .ToArray().
BUT, if it won't be anything like .ToList or .ToArray in the end - compiler will SKIP the second part of condition.
What is the problem? Is it normal? :)
UPDATE
Ok, thanks for your answers! I understood that it's normal. But the problem is that the 1st part of the condition contains: someobject == null; the second part contains: someobject.Contains().
.Where(x => someobject == null || someobject.Field.Contains(x.somefield))
So I have ArgumentNullException when someobject == null (my hope was that the 1st part will return true and the 2nd part WILL NOT execute). Could you advise me, how can I solve this problem?
P.S: actually, the .Where() expression is more complex:
.Where(x=> (part1 || part 2) && (part1 || part2) && ......)
You're doing Where on IQueryable and the argument is an Expression not a Func
http://msdn.microsoft.com/en-us/library/vstudio/bb535040%28v=vs.100%29.aspx
The Expression is just passed to the underlying Where implementation.
I found the subject interesting so I've created an example. Suppose we have following code:
using System;
using System.Linq.Expressions;
namespace TestApplication
{
class CompilerTest
{
public void Test()
{
Func<bool> func = () => true || Foo();
Expression<Func<bool>> expr = () => true || Foo();
}
public static bool Foo()
{
return new Random().Next() % 2 == 0;
}
}
}
We build it (Release build) and the decompiled code looks like this:
using System;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
namespace TestApplication
{
internal class CompilerTest
{
[CompilerGenerated]
private static Func<bool> CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate1;
public CompilerTest()
{
base.\u002Ector();
}
public void Test()
{
if (CompilerTest.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate1 == null)
{
// ISSUE: method pointer
CompilerTest.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate1 = new Func<bool>((object) null, __methodptr(\u003CTest\u003Eb__0));
}
Func<bool> func = CompilerTest.CS\u0024\u003C\u003E9__CachedAnonymousMethodDelegate1;
(Expression<Func<bool>>) (() => true || CompilerTest.Foo());
}
public static bool Foo()
{
return new Random().Next() % 2 == 0;
}
[CompilerGenerated]
private static bool \u003CTest\u003Eb__0()
{
return true;
}
}
}
and if we hide compiler generated code (dotPeek option) it looks like this:
using System;
using System.Linq.Expressions;
namespace TestApplication
{
internal class CompilerTest
{
public void Test()
{
Func<bool> func = (Func<bool>) (() => true);
(Expression<Func<bool>>) (() => true || CompilerTest.Foo());
}
public static bool Foo()
{
return new Random().Next() % 2 == 0;
}
}
}
As we can see the Func code specified in lambda was optimized (that was the real question if the compiler optimizes that). The code specified in expression was obviously not optimized (since it's an Expression so there is nothing to optimize at this point from the compiler perspective).
The answers so far touch some issues that play a role but don't cover the whole picture. Also, it is essential information that the second condition is a Contains statement. So let's say the core statement is
StavRealtyDb.TargetFlat.Where(x => true || someList.Contains(x.Id))
As said, the whole LINQ statement is an Expression, so the compiler doesn't apply any optimizations. So if all is well -
the .Net runtime succeeds in creating an expression,
passes it to the EF query provider,
the query provider translates it into SQL,
ADO.Net runs the SQL,
the database executes it, and returns a result set back to the .Net runtime,
the .Net runtime creates objects from the result set and returns them into var flat.
In this course of events, the second predicate is always read by the .Net runtime, irrespective of how many predicates precede it, but evaluated by the database if the query optimizer finds reasons to do so.
Now something's wrong: someList is null. Now the whole process comes to a halt at step 3. The query provider tries to read someList (in order to convert it to an IN clause). But, of course, that fails with a null reference.
So you have to make sure that someList is never null (it could be an empty list) or you could compose the Where condition: only if someList isn't null, you include the Contains predicate.
I think this is normal and by-design for Linq Providers. In this case the Linq Provider is designed to take the Where expression and turn it into Sql and execute it on the Sql Server.
Where() will return an IQueryable<>, which you can see as a query ready to be executed. It is, however, only built in the Where() and it will be executed whenever the actual data is needed - in this case, when calling ToList(). The query will hold the OR and thus it is completely normal behaviour that it is not short circuited because it is simply not executed within the Where().
If you'd like to understand it better, try splitting it up and put a breakpoint at the Where().
var query = StavRealtyDb.TargetFlat.Where(x => true || _some condition_);
var actualData = query.ToList();
When hovering over query while debugging, you will notice it being an actual query like
SELECT `Extent1`....
And after calling ToList(), you will notice that the data is retrieved from the database and put in a List.
I'm migrating some stuff from one mysql server to a sql server but i can't figure out how to make this code work:
using (var context = new Context())
{
...
foreach (var item in collection)
{
IQueryable<entity> pages = from p in context.pages
where p.Serial == item.Key.ToString()
select p;
foreach (var page in pages)
{
DataManager.AddPageToDocument(page, item.Value);
}
}
Console.WriteLine("Done!");
Console.Read();
}
When it enters into the second foreach (var page in pages) it throws an exception saying:
LINQ to Entities does not recognize the method 'System.String
ToString()' method, and this method cannot be translated into a store
expression.
Anyone know why this happens?
Just save the string to a temp variable and then use that in your expression:
var strItem = item.Key.ToString();
IQueryable<entity> pages = from p in context.pages
where p.Serial == strItem
select p;
The problem arises because ToString() isn't really executed, it is turned into a MethodGroup and then parsed and translated to SQL. Since there is no ToString() equivalent, the expression fails.
Note:
Make sure you also check out Alex's answer regarding the SqlFunctions helper class that was added later. In many cases it can eliminate the need for the temporary variable.
As others have answered, this breaks because .ToString fails to translate to relevant SQL on the way into the database.
However, Microsoft provides the SqlFunctions class that is a collection of methods that can be used in situations like this.
For this case, what you are looking for here is SqlFunctions.StringConvert:
from p in context.pages
where p.Serial == SqlFunctions.StringConvert((double)item.Key.Id)
select p;
Good when the solution with temporary variables is not desirable for whatever reasons.
Similar to SqlFunctions you also have the EntityFunctions (with EF6 obsoleted by DbFunctions) that provides a different set of functions that also are data source agnostic (not limited to e.g. SQL).
The problem is that you are calling ToString in a LINQ to Entities query. That means the parser is trying to convert the ToString call into its equivalent SQL (which isn't possible...hence the exception).
All you have to do is move the ToString call to a separate line:
var keyString = item.Key.ToString();
var pages = from p in context.entities
where p.Serial == keyString
select p;
Cast table to Enumerable, then you call LINQ methods with using ToString() method inside:
var example = contex.table_name.AsEnumerable()
.Select(x => new {Date = x.date.ToString("M/d/yyyy")...)
But be careful, when you calling AsEnumerable or ToList methods because you will request all data from all entity before this method. In my case above I read all table_name rows by one request.
Had a similar problem.
Solved it by calling ToList() on the entity collection and querying the list.
If the collection is small this is an option.
IQueryable<entity> pages = context.pages.ToList().Where(p=>p.serial == item.Key.ToString())
Hope this helps.
Upgrading to Entity Framework Version 6.2.0 worked for me.
I was previously on Version 6.0.0.
Hope this helps,
Change it like this and it should work:
var key = item.Key.ToString();
IQueryable<entity> pages = from p in context.pages
where p.Serial == key
select p;
The reason why the exception is not thrown in the line the LINQ query is declared but in the line of the foreach is the deferred execution feature, i.e. the LINQ query is not executed until you try to access the result. And this happens in the foreach and not earlier.
If you really want to type ToString inside your query, you could write an expression tree visitor that rewrites the call to ToString with a call to the appropriate StringConvert function:
using System.Linq;
using System.Data.Entity.SqlServer;
using System.Linq.Expressions;
using static System.Linq.Expressions.Expression;
using System;
namespace ToStringRewriting {
class ToStringRewriter : ExpressionVisitor {
static MethodInfo stringConvertMethodInfo = typeof(SqlFunctions).GetMethods()
.Single(x => x.Name == "StringConvert" && x.GetParameters()[0].ParameterType == typeof(decimal?));
protected override Expression VisitMethodCall(MethodCallExpression node) {
var method = node.Method;
if (method.Name=="ToString") {
if (node.Object.GetType() == typeof(string)) { return node.Object; }
node = Call(stringConvertMethodInfo, Convert(node.Object, typeof(decimal?));
}
return base.VisitMethodCall(node);
}
}
class Person {
string Name { get; set; }
long SocialSecurityNumber { get; set; }
}
class Program {
void Main() {
Expression<Func<Person, Boolean>> expr = x => x.ToString().Length > 1;
var rewriter = new ToStringRewriter();
var finalExpression = rewriter.Visit(expr);
var dcx = new MyDataContext();
var query = dcx.Persons.Where(finalExpression);
}
}
}
In MVC, assume you are searching record(s) based on your requirement or information.
It is working properly.
[HttpPost]
[ActionName("Index")]
public ActionResult SearchRecord(FormCollection formcollection)
{
EmployeeContext employeeContext = new EmployeeContext();
string searchby=formcollection["SearchBy"];
string value=formcollection["Value"];
if (formcollection["SearchBy"] == "Gender")
{
List<MvcApplication1.Models.Employee> emplist = employeeContext.Employees.Where(x => x.Gender == value).ToList();
return View("Index", emplist);
}
else
{
List<MvcApplication1.Models.Employee> emplist = employeeContext.Employees.Where(x => x.Name == value).ToList();
return View("Index", emplist);
}
}
I got the same error in this case:
var result = Db.SystemLog
.Where(log =>
eventTypeValues.Contains(log.EventType)
&& (
search.Contains(log.Id.ToString())
|| log.Message.Contains(search)
|| log.PayLoad.Contains(search)
|| log.Timestamp.ToString(CultureInfo.CurrentUICulture).Contains(search)
)
)
.OrderByDescending(log => log.Id)
.Select(r => r);
After spending way too much time debugging, I figured out that error appeared in the logic expression.
The first line search.Contains(log.Id.ToString()) does work fine, but the last line that deals with a DateTime object made it fail miserably:
|| log.Timestamp.ToString(CultureInfo.CurrentUICulture).Contains(search)
Remove the problematic line and problem solved.
I do not fully understand why, but it seems as ToString() is a LINQ expression for strings, but not for Entities. LINQ for Entities deals with database queries like SQL, and SQL has no notion of ToString(). As such, we can not throw ToString() into a .Where() clause.
But how then does the first line work? Instead of ToString(), SQL have CAST and CONVERT, so my best guess so far is that linq for entities uses that in some simple cases. DateTime objects are not always found to be so simple...
My problem was that I had a 'text' data type for this column (due to a migration from sqlite).
Solution: just change the data type to 'nvarchar()' and regenerate the table.
Then Linq accepts the string comparison.
I am working on retiring Telerik Open Access and replacing it with Entity Framework 4.0. I came across same issue that telerik:GridBoundColumn filtering stopped working.
I find out that its not working only on System.String DataTypes. So I found this thread and solved it by just using .List() at the end of my Linq query as follows:
var x = (from y in db.Tables
orderby y.ColumnId descending
select new
{
y.FileName,
y.FileSource,
y.FileType,
FileDepartment = "Claims"
}).ToList();
Just turn the LINQ to Entity query into a LINQ to Objects query (e.g. call ToArray) anytime you need to use a method call in your LINQ query.
I have a method query like this:
public IList<BusinessObject> GetBusinessObject(Guid? filterId)
{
using (var db = new L2SDataContext())
{
var result = from bo in db.BusinessObjects
where (filterId.HasValue)
? bo.Filter == filterId.value
: true
orderby bo.Name
select SqlModelConverters.ConvertBusinessObject(bo);
return result.ToList();
}
}
At runtime, this throws a System.InvalidOperationException: Nullable object must have a value.
Looking at the Debugger, the problem is my Where Clause: Linq To SQL tries to convert the entire thing to SQL, so even if filterId is NULL, it will still try to access filterId.value.
I thought/hoped the C# compiler/CLR would evaluate that where clause as a code block and only send one of the two branches to Linq To SQL, but that's not how it works.
My refactored version works, but is not very elegant:
public IList<BusinessObject> GetBusinessObject(Guid? filterId)
{
using (var db = new L2SDataContext())
{
var temp = from bo in db.BusinessObjects select bo;
if(filterId.HasValue) temp = temp.Where(t => t.Filter == filterId.Value);
var result = from t in temp
orderby t.Name
select SqlModelConverters.ConvertBusinessObject(bo);
return result.ToList();
}
}
I know that Lazy-Evaluation will make sure that only one query is really sent, but having that temp object in there isn't that great really.
Did you try:
where filterId == null || t.Filter == filterId
Your fix is exactly correct. You are effectively trying to build up a query dynamically, based on your function input. It's a good idea to omit the where clause instead of supplying WHERE TRUE anyway. If I were writing this query, I would go with your fixed version myself.
It's not as pretty as using the language keywords, but it's still the right way to approach the query in my opinion.
I have a Linq to Entities query like this one:
var results = from r in entities.MachineRevision
where r.Machine.IdMachine == pIdMachine
&& r.Category == (int)pCategory
select r;
Usually, I use the code below to check if some results are returned:
if (results.Count() > 0)
{
return new oMachineRevision(results.First().IdMachineRevision);
}
However, I'm getting NotSupportedException in the if condition.
The error message is: Unable to create a constant value of type 'Closure type'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
Note that pCategory is an Enum type.
EDIT: Based on your update, the error may be related to an enum in your entity class. See this blog entry for more information and a work-around. I'm leaving my original answer as an improvement on your query syntax.
Try doing the selection of the first entity in the query itself using FirstOrDefault and then check if the result is null.
int compareCategory = (int)pCategory; // just a guess
var result = (from r in entities.MachineRevision
where r.Machine.IdMachine == pIdMachine
&& r.Category == compareCategory
select r).FirstOrDefault();
if (result != null)
{
return new oMachineRevision(result.IdMachineRevision);
}
Why not just use FirstOrDefault() instead, and check for null? I can't see the benefit in querying for the count and then taking the first element.
In the standard implementation of linq, the operators "select" and "where" map to methods that return an IEnumerable or IQueryable. So standard linq methods when used should always return an IEnumerable from your query not a single object.
But linq methods that are candidates for the linq operators are not restricted to methods returning IEnumerables, any method returning anything can be chosen.
In case you have instance methods named "Select" and "Where" that return a single object or extensions methods that are specific to your class and return a single object those will be used instead of the standard linq ones.
My guess is that either a "Select" or "Where" method defined in your class is making linq return a single value instead of a IEnumerable<T>.
I didn't know different anonymous objects would be created depending on the query result. I guess they just wanted results to be of type IEnumerable
How about using a foreach?
var results = from r in entities.MachineRevision
where r.Machine.IdMachine == pIdMachine
&& r.Category == pCategory
select r;
foreach( var r in results )
{
yield return new oMachineRevision( r.IdMachineRevision );
}
This goes for all implicit types too. I must admit I keep forgetting this and that's how I came across this post.
if you have
class ClassA {
...
private string value;
...
public static implicit operator string(ClassA value)
{
return value.ToString();
}
...
}
you need to explictly cast the class to astring for comparison.
so I usually do this
var myClassAStr = myClassA.ToString();
var x = (from a in entites where a.ValToCompare == myClassAStr select a).first();
// do stuff with x
...
try using
IENumerable<MachineRevision> results = from r in entities.MachineRevision
...
instead.
I think its the var that's causing your issue.
Edit:
Read the error message. "Unable to create a constant value of type 'Closure type'. Only primitive types ('such as Int32, String, and Guid') are supported in this context."
One of these comparisions is with a type that is not int, string or guid. I'm guessing the Category.
r.Machine.IdMachine == pIdMachine && r.Category == pCategory
Interestingly, LinqToSql will allow this construction. Don't know why LinqToEntities does not support this.
I think you could also select the item you want another, simpler way by using lambda expressions.
var result = entities.MachineRevision
.Where(x => x.Machine.IdMachine == pIdMachine)
.Where(y => y.Category == (int)pCategory)
.FirstOrDefault();
if (result != null)
{
return new oMachineRevision(result.IdMachineRevision);
}
and then proceeding as you would normally