11

The new C# driver is totally Async and in my understanding twists a little bit the old design patterns such as DAL in n-tier architecture.

In my Mongo DALs I use to do:

public T Insert(T entity){
     _collection.Insert(entity);
     return entity;
}

This way I can get the persisted ObjectId.

Today, everything is Async such as InsertOneAsync.
How would Insert method will now return the entity when the InsertOneAsync will be done? Can you show an example?

shA.t
  • 16,580
  • 5
  • 54
  • 111
SexyMF
  • 10,657
  • 33
  • 102
  • 206

2 Answers2

18

It's helpful to understand the basics of async / await because it's a somewhat leaky abstraction and has a number of pitfalls.

Essentially, you have two options:

  • Remain synchronous. In this case, it's safe to use .Result and .Wait() on the async calls, respectively, e.g. something like

    // Insert:
    collection.InsertOneAsync(user).Wait();
    
    // FindAll:
    var first = collection.Find(p => true).ToListAsync().Result.FirstOrDefault();
    
  • Go async in your code base. Doing it async is quite 'infectious', unfortunately, so either you convert pretty much everything to async, or not. Careful, mixing sync and async incorrectly will lead to deadlocks. Using async has a number of advantages, because your code can continue to run while MongoDB is still working, e.g.

    // FindAll:
    var task = collection.Find(p => true).ToListAsync();
    // ...do something else that takes time, be it CPU or I/O bound
    // in parallel to the running request. If there's nothing else to 
    // do, you just freed up a thread that can be used to serve another 
    // customer...
    // once you need the results from mongo:
    var list = await task;
    
mnemosyn
  • 45,391
  • 6
  • 76
  • 82
  • Using MongoDB synchronously would be like calling an SQL database with a classic ASP application ? Would it lock the entire website until the call is over ? – RPDeshaies Jun 02 '15 at 17:54
  • Do you need to add something specific to make the `await task` line work? It keeps yelling that `await` needs to be done on something `async`.. but of course it is, since `.ToListAsync()` is there. Any idea what could be the issue?? @mnemosyn – Mark Pieszak - Trilon.io Oct 20 '15 at 19:18
  • @mcpDESIGNS: `await` can only be used from methods that are declared `async`. – mnemosyn Oct 21 '15 at 07:49
  • I typically use Mongo with Node/mongoose so it just seems strange to me here in the C# world. I tried `async Task FooAsync(IMongoCollection collection)` as a method and that worked. Thanks. I suppose chaining them inside of each other is the next part that's going to confuse me... haha – Mark Pieszak - Trilon.io Oct 21 '15 at 13:22
  • Async/await should be pretty close to what node does... Anyway, I suggest you step back a bit and start with a little trivial async console application that doesn't use an async library... Also, `IMongoCollection` doesn't look good to me (why not strongly typed?) But that leads too far from the original question... – mnemosyn Oct 21 '15 at 13:25
0

In my case: When I got this error:

The source IQueryable doesn't implement IAsyncEnumerable. Only sources that implement IAsyncEnumerable can be used for Entity Framework asynchronous operations.

I have implemented the async where function for mongodb as follows.

public async Task<IEnumerable<TEntity>> Where(Expression<Func<TEntity, bool>> expression = null)
{
     return await context.GetCollection<TEntity>(typeof(TEntity).Name, expression).Result.ToListAsync();
}
Hamit YILDIRIM
  • 4,224
  • 1
  • 32
  • 35