How to link multiple Query Operations in MongoDb C# Driver - c#

I'm trying to create a complex query expression with the MongoDb C# driver. So far I've mostly relied on the LINQ .AsQueryable() features which work great, but now I need to run some update operations and it looks like I need to use the QueryBuilder for that.
However, I can't figure out how to create a complex query that strings multiple query operators together.
I'd like to do something like this:
var query = Query<QueueMessageItem>
.EQ( qi => qi.Type, queueName)
.EQ("Started", null);
but apparently this doesn't work because .EQ() and all the other query operators don't return a chainable Query object.
How do I use Queries and add multiple search operators?

You need to nest the query operators. Something like this
Query.Or(Query.EQ("t", "F"), Query.EQ("t", "M"))

Related

LINQ join on two variable with different types

I am re-writing an Query from Progress4GL to an IQueryAble statement in LINQ and would like to join two tables on keys that have different types. In Progress4GL casting is done fairly easily but I having trouble writing the same Query in linq/C#.
Since this is a custom build Query Engine, certain functionality such as ToString() is not implemented yet for the Iqueryable conversion, and was looking for a way to get past this issue without having to implement it.
Since this is a custom Engine, supporting Linq in the format of data.Where(x => x...).OrderBy()... is does not work (to some extent). Below is the example I am writing:
var query = from invbinlotalloc in Query()
join putline in QueryOver<Putline>()
on invbinlotalloc.keyId equals putline.putlineId
select invbinlotalloc;
var data = await ExecuteAsync(query, cancellationToken).ConfigureAwait(false);

How to filter and order collection in C#?

Here is the code:
public ActionResult Index()
{
var crView = db.CRCases.ToList();
return View(crView);
}
Would like to filter like we have in sql statement using WHERE and ORDER BY.
Is there any good reference on how to apply it?
linq is your friend here.
you can do
crView = crView.Where(x => x.yourPredicate).OrderBy( y => y.OrderClause);
CRCases should be a DBSet<T>. You can use LinQ like this :
db.CRCases.Where(x => x.TheProperty =xxx).ToList()
You can use LINQ = Language Integrated Query.
This have two different notations:
Functional: you can change several function calls beginning on an IEnumerable.
db.CrCases.Where(predicate).OrderBy(sortExpression)
"SQL like": it really looks like an "unordered SQL".
from crCase in db.CrCases where condition orderby sortExpression select crCase
The condition and sort expression in the first notation require lambda expressions (you can see them in action here). In the second case the condition is expressed.
Most of the queries can be written either way.
You'll usually use var to store the query, and materialize it later.
var query = from crCase in db.CrCases
where condition orderby sortExpression
select crCase
CrCase firstCase = query.Firts();
List<CrCase> cases = query.ToList();
There are several flavors of LINQ. They all look equal on the surface, but are translated into another thing. For example:
LINQ to objects: it's the more general, an allows to make queries on collections. Tis is what you'll use for this particular case.
LINQ to SQL: this allows to write queries in C# which are transalated to SQL queries in the underlying database
LINQ to Entities: similar to the previous, but you make your queries to an Entity Framework model, and the queries are finally transalated to the DB
There are some others flavors of LINQ. And, in fact, you can create your own, but that's not easy.
Finally, you have to take into account that a LINQ query isn't executed until you materialize it. I.e. it's not executed until you try to get data from it (converting it ToList(), ToArray() or whatever, enumerating it, or accesing any of it's data First(), Sum(), Count()). Depending on the flavor, the executing can be running C# code (LINQ to objects) or run a SQL Query in a DB (LINQ to SQL) or whatever.
Here you have a great place to learn how to use LINQ:
LINQ 101

Linq query with MongoDB works does not work as Func

I built a Linq query on a MongoDB collection, which retrieves properly my docs:
var parts = mongoParts.AsQueryable()
.Where(mongo => mongo.Prop1 == bmbMatch.Prop1 && mongo.Prop2 == bmbMatch.Prop2)
.ToList();
This works fine, but to make this less code I wrote a Generic function taking a
Func<T, T, bool> selector
Which take the exact same lamdba expression as in Where clause above, which makes it:
var mongo = mongoQuery.AsQueryable()
.Where(tmongo => selector(tmongo, localMatch))
.ToList();
with selector as :
(mongo, local) => mongo.Prop1== local.Prop1 && mongo.Prop2 == local.Prop2
This gives me a "Unsupported where clause: "
Any ideas?
From the internet
Not all LINQ queries can be turned into equivalent MongoDB queries,
because C# allows you to write expressions that don't have any
equivalent in the MongoDB query language.
That being said, LINQ to MongoDB probably can't translate delegates.
You can find all supported LINQ queries on this address.
Conclusion: If you need to query very large data or make queries as fast as possible, you will have to stick with the former solution. Otherwise, pull all data from your db and query them in-memory.

Linq To SQL: Sort Query by Arbitrary Property(Column) Name

I have a larger/more complex problem, but for simplicity sake, let us consider the following:
Let us say that I have table in the SQL DataBase called Product, having two columns, ID (int, primary key) and Name (varchar/string). I also have a simple LINQ DataContext.
I have a query constructed and handed to “my” function. Let us say it is something like: (though it may be a bit more complex)
IQueryable<Product> query = from p in db.Products select p;
Once my method gets this query, passed in as a parameter, it has to change the sort order e.g.
IQueryable<Product> sortedQuery = query.OrderBy(x => x.Name);
I would like to make this more generic i.e. to specify the field to sort on. Normally, I can do a switch statement that takes a string. However I would like to know if there is a way to pass the parameter directly. I intend to extend this to other Database tables, so these switch statements would get tedious.
I was trying something like:
IQueryable<Product> sortedQuery = query.OrderBy(x => (typeof(Product)).GetProperty(“Name”));
But this does not work. I also want to ensure that the LINQ to SQL is maintained i.e. the sort to be done on the SQL Server. Hence if I debug, I should get a SQL query from this LINQ query.
Thank you in advance for your help.
You could use Dynamic Linq for this purpose.
See here Dynamic LINQ (Part 1: Using the LINQ Dynamic Query Library)
Then you can make calls like this:
var query = DBContext.Users.Where( "Age > 3" ).OrderBy( "Name asc" );
Try this out instead:
query.OrderBy(x => x.GetType().GetProperty(“Name”).GetValue(x, null));
You can't just grab the property. You need to grab the value off of that property, hence the call to GetValue.
It is not as easy as it seems. The LINQ to SQL engine parses the expression you pass to the OrderBy method in order to obtain the name of the property you are referencing, then uses this information to compose a plain SQL order by clause.
I guess that maybe it can be done by using reflection, anyway. Maybe you can get something useful from the accepted answer of this SO question.

LINQ - Remove Parts of Expression Tree

I have the following LINQ query:
var query = session.Query<Event>()
.Fetch(e => e.Venue); // Fetch is an IQueryable extension which does a join
// Code needed here to remove the fetch part
var num = query.Count(); // This then hits the database
Unfortunately this throws an error as fetch is not supported for a count method. At this stage i'm sure you're thinking why don't i remove the fetch part. However i have simplified my example and this is not possible. What i'd ideally like to be able to do is navigate the expression tree for the LINQ query and remove any calls to Fetch before i call Count.
I'd appreciate it if someone could show how this is possible. Thanks
It is possible to change expression trees at runtime (by building a new one out of the existing one), since O/RM tools such as LINQ to SQL and Entity Framework do this constantly, but it's not really easy. It has become easier with the introduction of the ExpressionVisitor class of .NET 4.0, but still don't expect it to be simple.
Here is an article that shows an example of this.
Would it help to convert the query to an Enumerable and call Count() on this like this:
var num = query.AsEnumerable().Count();
This would execute the query and afterwards makes a simple Count() on the result instead of letting the Count() flow into the ExpressionTree.

Categories