Lambda Expression for "not in" is not working - c#

I have a lambda expression as follows:
var queryResult = _tableClient.QueryAsync<SyncJob>(
x => x.Status != "Idle" && x.Status != "InProgress" && x.Status != "Error");
which works fine.
I updated this to:
var statuses = new List<string>() {
"Idle",
"InProgress",
"Error"
};
var queryResult = _tableClient
.QueryAsync<SyncJob>(x => !statuses.Contains(x.Status));
I see the following exception:
at Azure.Data.Tables.TableClient.Bind(Expression expression)
---> System.NotSupportedException: Method Contains not supported.
What am I missing?

Related

How can I solve my error below with a query?

When running this code:
public async Task<IActionResult> AddMessage()
{
int distid = ViewBag.DISTRIBUTORID;
ViewBag.PageName = "Send Message";
int id = Convert.ToByte(ViewBag.ID);
ViewBag.UserId = id;
var messages = await _companyContext.MESAJLAR.Where(p => p.SENDERID == id || p.SENTID == id).OrderBy(p => p.DATE).GroupBy(p => p.SPECIALID).Select(p => p.Last()).ToListAsync();
var ids1 = messages.Select(p => p.SENDERID).ToArray();
var ids2 = messages.Select(p => p.SENTID ).ToArray();
var users= await _userDatabaseContext.user.Where(p => p.DISTID == distid && p.ID != id && !ids1.Contains(p.ID) && !ids2.Contains(p.ID)).ToListAsync();
return View(new AddMessageViewModel
{
USERS= users
});
}
I get the following error:
Queries performing 'Last' operation must have a deterministic sort order.Rewrite the query to apply an 'OrderBy' operation on the sequence before calling 'Last'.
I'm getting it at the line that starts with var messages = ...
The Problem with your query is, that you are trying to select .Last() without ordering your data first.
Right now you are ordering your data, then group it and after that you try to select 'Last()'.
You have to order the grouped data to use '.Last()'.
var messages = await _companyContext.MESAJLAR.Where(p => p.SENDERID == id || p.SENTID == id).OrderBy(p => p.DATE).GroupBy(p => p.SPECIALID).OrderBy(p => p.XXXXX).Select(p => p.Last()).ToListAsync();
And your first order would probably be not needed anymore.

How to use Query to add value in IQueryable?

I want to add a value in IQueryable get from another IQueryable here is my code
var queryReturnRequest = query.Include(x => x.Assignment)
.ThenInclude(x => x.Asset).Select(x => new ReturnRequestDto
{
AssetCode = x.Assignment.Asset.Code,
AssetName = x.Assignment.Asset.Name,
Id = x.Id,
ReturnDate = x.ReturnDate,
AssignedDate = x.Assignment.AssignedDate,
State = x.State,
UserRequestId = x.UserRequestId,
UserAcceptId = x.UserAcceptId,
RequestedBy = userList.FirstOrDefault(u => u.Id == x.UserRequestId) != null ? userList.FirstOrDefault(u => u.Id == x.UserRequestId).UserName : "",
AcceptedBy = userList.FirstOrDefault(u => u.Id == x.UserAcceptId) != null ? userList.FirstOrDefault(u => u.Id == x.UserAcceptId).UserName : "",
});
But it was crashed and return error 500, I found out that was because of userList.FirstOrDefault but when I console.log() it just work fine. So what wrong with it and is there another way to add it in IQueryable ?
I tried to user for loop to add IQueryable but it just return to null after get our of loop.
Try rewrite query in the following way. Also note that Select discards Includes, so avoid them in such case.
var queryReturnRequest = query
.Select(x => new ReturnRequestDto
{
AssetCode = x.Assignment.Asset.Code,
AssetName = x.Assignment.Asset.Name,
Id = x.Id,
ReturnDate = x.ReturnDate,
AssignedDate = x.Assignment.AssignedDate,
State = x.State,
UserRequestId = x.UserRequestId,
UserAcceptId = x.UserAcceptId,
RequestedBy = userList.Where(u => u.Id == x.UserRequestId).Select(x => x.UserName).FirstOrDefault() ?? "",
AcceptedBy = userList.Where(u => u.Id == x.UserAcceptId).Select(x => x.UserName).FirstOrDefault() ?? "",
});

Using reflection throws error in EF Core 3

We formerly used reflection to create linq queries, e.g. for the GetById method:
private IQueryable<T> GetQueryById(TKey id)
{
var query = _dbset; //DbSet<T>
var keyNames = _context.Model
.FindRuntimeEntityType(typeof(T))
.FindPrimaryKey()
.Properties
.Select(x => x.Name)
.ToList();
if (keyNames.Count() == 1)
{
query = query.Where(e => e.GetType().GetProperty(keyNames[0]).GetValue(e, null)
.Equals(id)); //throws error
}
return query;
}
This does not seem to work any more in EF Core 3:
The LINQ expression 'DbSet
.Where(c => c.GetType().GetProperty(__get_Item_0).GetValue(
obj: c,
index: null).Equals((object)__id_1))' could not be translated.
Is it possible to rewrite the query so that EF Core does not complain?
You have to create predicate dynamically:
private IQueryable<T> GetQueryById(TKey id)
{
IQueryable<T> query = _dbset; //DbSet<T>
var keyNames = _context.Model
.FindRuntimeEntityType(typeof(T))
.FindPrimaryKey()
.Properties
.Select(x => x.Name)
.ToList();
if (keyNames.Count == 1)
{
var keyExpression = Expression.Constant(id);
var entityParam = Expression.Parameter(typeof(T), "e");
var body = Expression.Equal(Expression.PropertyOrField(entityParam, keyNames[0]), keyExpression);
var predicate = Expression.Lambda<Func<T, bool>>(body, entityParam);
query = query.Where(predicate);
}
else
// better to throw exception
throw new Exception($"Cannot find entity key.");
return query;
}

String to LINQ expression? [duplicate]

This question already has answers here:
Linq - check condition in where clause if field can be null
(3 answers)
Closed 4 years ago.
How can I transform the string with the query in it into an actual LINQ expression so I can execute it?
if(email!= null)
{
query += "x => x.Email.Contains(email)";
}
if (firstname != null)
{
query += "&& x.FirstName.Contains(firstname)";
}
if (lastname != null)
{
query += "&& x.LastName.Contains(lastname)";
}
return context.UserAccounts.Where(query).ToList();
Try this:
<your collection>.
.Where(o => (email!= null)? o.Email.Contains(email) : true).
.Where(o => (firstname != null)? o.FirstName.Contains(firstname) : true).
.Where(o => (lastname != null)? o.LastName.Contains(lastname) : true).
ToList();
Basically it means the filter will apply only when the condition is met (just like in your if sentences).
If the query is required with the combination of where clauses then every time result needs to be saved in query itself
var query = context.UserAccounts;
if(email != null)
{
query = query.Where(x => x.Email.Contains(email));
}
if (firstname != null)
{
query = query.Where(x => x.FirstName.Contains(firstname));
}
if (lastname != null))
{
query = query.Where(x => x.LastName.Contains(lastname));
}
return query.ToList();
Another complex approach could be to use Actions
Instead of saving your query as a string you could save it as an IQueryable (from the System.Linq namespace).
var query = context.UserAccounts;
if(email!= null)
{
query = query.Where(x => x.Email.Contains(email));
}
if (firstname != null)
{
query = query.Where(x => x.FirstName.Contains(firstname));
}
if (lastname != null)
{
query = query.Where(x => x.LastName.Contains(lastname));
}
return query.toList();
When you finally call ToList() the IQueryable is enumerated to a List of UserAccount.
Maybe I'm not seeing your problem correctly so excuse me if i'm wrong.
Why convert the string to a LINQ expression when you can do this:
var query = context.UserAccounts;
if(email != null)
{
query = query.Where(x => x.Email.Contains(email));
}
if (firstname != null)
{
query = query.Where(x.FirstName.Contains(firstname));
}
if (lastname != null))
{
query = query.Where(x.LastName.Contains(lastname));
}
return query.toList();

Expression failure

I've got such expression:
Linq2Rest.Reactive.InnerRestObservable`1[A]
.Where(item => (Convert(IIF((item != null), item.ID, 0)) == Convert(61)))
.Skip(0)
.Take(20)
When I invoke Subscribe method on it I recieve such error:
variable 'item' of type 'A' referenced from scope '', but it is not defined
Can't figure out what is the problem. Actually can't see any problems with item argument...
UPD.
Where clause built with this code:
public static IQbservable WhereExpression(this IQbservable query, Expression filterExpression, ParameterExpression instance = null)
{
if (instance == null)
instance = Expression.Parameter(query.ElementType, "item"); // NOI18N
var filteredQuery = (IQbservable)GenericsHelper.InvokeGenericExtensionMethod(
typeof(Qbservable),
"Where", // NOI18N
new[] { query.ElementType },
query,
Expression.Lambda(filterExpression, instance)
);
return filteredQuery;
}
public static object InvokeGenericExtensionMethod(
Type extensionClass,
string extensionMethodName,
Type[] genericTypes,
params object[] parameters
)
{
var method = extensionClass.GetMethods().FirstOrDefault(m =>
m.Name == extensionMethodName &&
m.IsGenericMethod &&
m.GetGenericArguments().Length == genericTypes.Length &&
m.GetParameters().Length == parameters.Length
);
if (method == null)
throw new ArgumentException(string.Format("Type {0} doesn't contain method {1}", extensionClass.Name, extensionMethodName)); // NOI18N
var genericMethod = method.MakeGenericMethod(genericTypes);
return genericMethod.Invoke(null, parameters);
}
UPD 2. This is how WhereExpression calls:
foreach (var filter in filters)
{
var paramExpression = Expression.Parameter(query.ElementType, "item"); // NOI18N
query = query.WhereExpression(filter.CreateFilterExpression(paramExpression), paramExpression);
}
filters is collection of IFilterDescriptor interface from telerik.
You need to use the same ParameterExpression instance both as the parameter and in the body of the expression.
The easiest thing would be to simply use the one from the filter expression, by using it completely.

Categories

Resources