When I try to run a LINQ query of the form:
MongoCollection<MyEntity> collection;
collection.AsQueryable().Where(entity =>
(entity.Flags & MyFlags.AFlag) != MyFlags.None);
I get an ArgumentException
with the message Unsupported where clause: ((Int32)((Int32)entity.Flags & 4) != 0).
Is this a known bug/feature?
Is there any workaround?
From the documentation it seems like MongoDB has a bitwise update, but not a bitwise query.
For comparison, the same query runs smoothly above Redis using ServiceStack as a client.
I did find these two links (link1, link2) which suggest using JavaScript, however, that would make the implementation of the service layer very dependant on the DB technology.
My solution has two parts. I made a serializer for Enum flags that stores all the values in a list of strings. I made an extension method for Linq to "inject" the mongo query i need.
public static IQueryable<TItem> HasFlags<TItem, TProperty>(
this IQueryable<TItem> items,
Expression<Func<TItem, TProperty>> itemPropertyExpression,
params Enum[] enumFlags)
{
var enumFlagNames = enumFlags.Select(enumFlag => (BsonValue)enumFlag.ToString());
return items.Where(item => Query.In(ExtendedObject.GetPropertyName(itemPropertyExpression), enumFlagNames).Inject());
}
That way, its both readable and i don't need to deserialize all the objects into memory.
P.S: The GetPropertyName method is just a type safe way to get the property name:
public static string GetPropertyName<TClass, TProperty>(
Expression<Func<TClass, TProperty>> entityPropertyExpression)
{
return ((MemberExpression)entityPropertyExpression.Body).Member.Name;
}