Below is my linq expression:
ListName.Except(xxx)
.Where(x => x.columnname != "xyz");
Can someone help in converting this expression to c++.net?
You can use Linq methods in C++/CLI, but you cannot use the Lambda syntax. Instead, you need to turn it into a full-fledged method, and pass that as a delegate.
static bool NotBannedColumnName(ColumnObject x)
{
return x.columnname != "xyz";
}
ListName.Except(xxx).Where(gcnew Func<TSource, bool>(&ThisClass::NotBannedColumnName));
Related
I have a nice Linq challenge. I would like to filter some data on a Date using a FilterFunction. It should work like this:
ApplyDateFilterEx(query,null, DateTime.Today, s => s.CreatedDate);
Should filter the query so that all 'shipments' until today are returned. The query object is of IQueryable and the whole query should be evaluated by EF5 and therefore should convert to SQL.
This is what I have so far (DOES NOT COMPILE):
private static IQueryable<Shipment> ApplyDateFilterEx(IQueryable<Shipment> query, DateTime? minDate, DateTime? maxDate, Expression<Func<Shipment, DateTime?>> dateMember)
{
if (minDate != null)
{
//convert func to expression so EF understands
Expression<Func<Shipment, bool>> where = x => minDate <= dateMember(x);
query = query.Where(where);
}
if (maxDate != null)
{
Expression<Func<Shipment, bool>> where = x => dateMember(x) <= maxDate;
query = query.Where(where);
}
return query;
}
You can see I want to convert the expression s=>DateTime? to s=> Bool to be evaluated. How can I get this to work?
Thank you for reading.
Martijn
UDPATE:
I ended up with this (thanks to rdvanbuuren)
var predicate = Expression.Lambda<Func<Shipment, bool>>(
Expression.GreaterThanOrEqual(
selector.Body,
Expression.Constant(dateFilter.MinDate, typeof (DateTime?))
), selector.Parameters);
Have a look at
How to implement method with expression parameter c#
I think that's exactly what you need, but with an Expression.GreaterThanOrEqual or Expression.LessThanOrEqual. Good luck!
More a general question, but how can I write LINQ Lambda expressions such that they will return a default string or simply an empty string if the LINQ expression fails or returns nothing. In XSLT XPath if a match fails then one just got nothing, and the application did not crash whereas in LINQ one seems to get exceptions.
I use First() and have tried FirstOrDefault().
So example queries may be:
Customers.First(c=>c.id==CustId).Tasks.ToList();
or
Customers.Where(c=>c.id==CustId).ToList();
or
Model.myCustomers.Where(c=>c.id==CustId);
etc.
Whatever the query, if it returns no records or null, then is there a general approach to ensure the query fails gracefully?
Thanks.
There isn't anything elegant built into C# for propagating nulls when you access properties. You could create your own extension methods:
public static class Extensions
{
public static TValue SafeGet<TObject, TValue>(
this TObject obj,
Func<TObject, TValue> propertyAccessor)
{
return obj == null ? default(TValue) : propertyAccessor(obj);
}
public static IEnumerable<T> OrEmpty<T>(this IEnumerable<T> collection)
{
return collection ?? Enumerable.Empty<T>();
}
}
Used like this:
Customers.FirstOrDefault(c => c.id==CustId).SafeGet(c => c.Tasks).OrEmpty().ToList();
Customers.First(c=>c.id==CustId) will crash if there is no matching record.
There are few ways you can try to find it, if you use FirstOrDefault that'll return NULL if no match is found and you can check for NULL.
Or, you can use the .Any syntax which checks if you have any record and returns boolean.
The only query I would expect to throw an exception would be the first one (assuming that Customers is a valid collection and not null itself):
Customers.First(c=>c.id==CustId).Tasks.ToList();
This will throw an exception if there is no customer with an id of CustId (you have some casing issues with your property and variable names).
If you don't wish to throw an exception on no match, then use FirstOrDefault as you mention, and do a null check, e.g:
var customer = Customers.FirstOrDefault(c => c.id == CustId);
if (customer == null)
{
// deal with no match
return;
}
var taskList = customer.Tasks.ToList();
The following statement works fine if the source is not null:
Filters.Selection
.Select(o => new GetInputItem() { ItemID = o.ItemId })
It bombs if "Filters.Selection" is null (obviously). Is there any possible way to write my own extension method which returns null if the source is null or else execute the "Select" func, if the source is not null.
Say, something like the following:
var s = Filters.Selection
.MyOwnSelect(o => new GetInputItem() { ItemID = o.ItemId })
"s" would be null if "Filters.Selection" is null, or else, "s" would contain the evaluated "func" using LINQ Select.
This is only to learn more about LINQ extensions/customizations.
thanks.
You could do this:
public static IEnumerable<U> SelectOrNull<T,U>(this IEnumerable<T> seq, Func<T,U> map)
{
if (seq == null)
return Enumerable.Empty<U>(); // Or return null, though this will play nicely with other operations
return seq.Select(map);
}
Yes have a look at the Enumerable and Queryable classes in the framework, they implement the standard query operators.
You would need to implement a similar class with the same Select extension methods matching the same signatures, then if the source is null exit early, you should return an empty sequence.
Assuming you're talking about LINQ to Objects, absolutely:
public static class NullSafeLinq
{
public static IEnumerable<TResult> NullSafeSelect<TSource, TResult>
(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
{
// We don't intend to be safe against null projections...
if (selector == null)
{
throw new ArgumentNullException("selector");
}
return source == null ? null : source.Select(selector);
}
}
You may also want to read my Edulinq blog post series to learn more about how LINQ to Objects works.
I am trying to get the following method to work:
private static IQueryable<TObject> ApplyOrderBy<TObject, TKey>(IQueryable<TObject> query, OrderByDirection orderByDirection,
Expression<Func<TObject, TKey>> sortExpression, ref bool first)
{
if (orderByDirection == OrderByDirection.None || sortExpression == null) return;
if (orderByDirection != OrderByDirection.Ascending && orderByDirection != OrderByDirection.Descending)
throw new Exception(string.Format("Should never get here! Unknown OrderByDirection enum - '{0}'.", orderByDirection));
if (first)
{
first = false;
query = orderByDirection == OrderByDirection.Ascending
? query.OrderBy(sortExpression)
: query.OrderByDescending(sortExpression);
}
else
{
query = orderByDirection == OrderByDirection.Ascending
? ((IOrderedQueryable<TObject>)query).ThenBy(sortExpression)
: ((IOrderedQueryable<TObject>)query).ThenByDescending(sortExpression);
}
return query;
}
This method works great if you call it like this:
ApplyOrderByToGet(ref query, OrderByDirection.Ascending, x => x.StartDateTime, ref first);
The sort expression then has a strongly typed DateTime as the type and LINQ to SQL is happy. However, if you want to pass an array of these expressions with varying types, you ultimately need a list with "object" as the type. Problem is that LINQ to SQL does not figure out that the type is not object, but instead is DateTime. This works with a regular list using LINQ to objects.
Seeing as it’s possible to navigate the expression tree and find out what the type is, would it be possible to cast/convert the expression before calling ApplyOrderBy?
Cast or convert from:
Expression<Func<T, object>>
to:
Expression<Func<T, DateTime>>
I write this method:
public List<TResult2> SelectAndJoin<TOuter, TInner, TKey, TResult, TResult2>(IEnumerable<TInner> inner,
System.Linq.Expressions.Expression<Func<Regions, TKey>> outerKeySelector,
System.Linq.Expressions.Expression<Func<TInner, TKey>> innerKeySelector,
System.Linq.Expressions.Expression<Func<Regions, TInner, TResult>> resultSelector,
Func<Regions, TResult2> selector)
{
using (RepositoryDataContext = new DataClasses1DataContext())
{
return RepositoryDataContext.Regions.Join(inner, outerKeySelector, innerKeySelector, resultSelector).AsEnumerable<TResult2>().Select<Regions, TResult2>(selector).ToList<TResult2>();
}
}
but the expression follow return has this Error:
'System.Linq.IQueryable' does not contain a definition for 'AsEnumerable' and the best extension method overload 'System.Linq.Enumerable.AsEnumerable(System.Collections.Generic.IEnumerable)' has some invalid arguments
How I can get rid of this error?
is this code standard?
thanks
You're calling AsEnumerable<TResult2> on enumerable which will be of type IQueryable<TResult>. You should call AsEnumerable<TResult> or you can even omit generic parameter and call AsEnumerable()
Also your next select will not work for the same reason - you are providing wrong types for generics.
I might be missing the point... but:
IQueryable inherits from IEnumerable so I think that AsEnumerable() is unnecessary in this code.
If you really do need/want to execute the query before doing the Select, then you could use ToList() instead of AsEnumerable() - this would be clearer
I'm also wondering if you are including using System.Linq in your .cs file - as AsEnumerable() is an extension method within System.Linq