XPO - Async/Await Method Support (v18.2)

With v18.2, XPO's Session and other key classes ship with a set of async APIs, including FindObjectAsync, GetObjectByKeyAsync, CommitChangesAsync (which return System.Threading.Tasks.Task object).

These Task-based APIs are important for both server and client programming (useful for long and DB-intensive operations like commits, queries, delete operations, etc.) as they improve server scalability and deliver a more resilient user experience, especially on mobile devices.

To see how asynchronous CRUD operations work with XPO, refer to the following code from an ASP.NET Core MVC application:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using DevExpress.Xpo.AspNetCoreMvcDemo.Models;
using DevExpress.Xpo.Demo.Entities;

namespace DevExpress.Xpo.AspNetCoreMvcDemo.Controllers {
    public class DataController : Controller {
        readonly UnitOfWork uow;
        public DataController(UnitOfWork uow) {
            this.uow = uow;
        }
        public async Task<IActionResult> Index() {
            var users = await uow.Query<User>()
                .OrderBy(u => u.LastName)
                .ThenBy(u => u.FirstName)
                .Select(u => new UserModel {
                    Oid = u.Oid,
                    FirstName = u.FirstName,
                    LastName = u.LastName,
                    Email = u.Email
                }).ToListAsync();
            
            int totalCount = await uow.Query<User>().CountAsync();
            
            var viewModel = new DataViewModel() {
                Users = users,
                TotalCount = totalCount
            };
            return View(viewModel);
        }
        [HttpPost]
        public async Task<IActionResult> Delete(Guid id) {
            var user = await uow.GetObjectByKeyAsync<User>(id);
            if(user != null) {
                uow.Delete(user);
                await uow.CommitChangesAsync();
            }
            return RedirectToAction("Index");
        }
        [HttpPost]
        public async Task<IActionResult> Create(UserModel model) {
            if(model != null) {
                var newUser = new User(uow) {
                    FirstName = model.FirstName,
                    LastName = model.LastName,
                    Email = model.Email
                };
                await uow.CommitChangesAsync();
            }
            return RedirectToAction("Index");
        }
    }
}

To get started, simply download our GitHub demo. See also the Asynchronous Programming Patterns and Task-based Asynchronous Pattern articles in Microsoft .NET Guide.

Please note that XPCollection.LoadAsync and XPView.LoadAsync will not return Task and thus will not support async/await. We recommend that you use XPQuery<T>  instead - it is a more efficient way to query data. Refer to this FAQ for more information.

Your feedback counts!

Everyone can use our https://www.nuget.org/packages/DevExpress.Xpo/ Nuget package - it's free.  Check the Include prerelease option when finding and installing the package:

Once you’ve had the opportunity to try this new feature in your upgraded v18.2 project, feel free to report issues and suggestions via the DevExpress Support Center.  By offering early build access, we hope to discover whether our new features and solutions effectively address your requirements. Your assistance and feedback will help us deliver the best possible solution.

Before we let you go, please take a moment to answer the following survey question:

As always, thank you very much for your feedback. 

15 comment(s)
tzanis tasos

It's looks grade!

16 October, 2018
Bert Stomphorst

Great, thank you DevExpress!

16 October, 2018
Martin Praxmarer - DevExpress MVP

Great - are there also plans to extend XAF's IObjectSpace to async/await ?

16 October, 2018
James Lincoln

Appreciate the core enhancement

16 October, 2018
Michael Gross

Great, thanks!

16 October, 2018
Dennis (DevExpress Support)

Thank you for your comments, Guys.

@Martin Praxmarer: If we improve XAF WinForms UI to support asynchronous operations (could not get our hands to it this year), this will be a natural move. This XPO feature is definitely the first step in this direction.

16 October, 2018
Martin Praxmarer - DevExpress MVP

perfect!

16 October, 2018
Maciej Ruszniak

What about multithread application. It can make collision without using mutexs etc.

16 October, 2018
Aluron

Is there a chance to get something like progress of long database operation, like big commit?

16 October, 2018
Dmitri Peredera

Will it accept cancellationToken that aborts long operation?

I had a problem to delete 500.000 records in WinForms and it takes a few minutes, so progress and abort would be nice.

18 October, 2018
SaiKan

@Dmitri - issues/process like that I simply wrap in a background worker process.

19 October, 2018
Paul Kubb

if this applied to xaf soon or later, could it improve scalabiliy of the total xaf as well?

19 October, 2018
Dennis (DevExpress Support)

@Maciej Ruszniak:

>>What about multithread application. It can make collision without using mutexs etc.

Would you please describe your use-case scenario and problem in the Support Center (https://www.devexpress.com/ask)? With that, we will be in a better position to help you.

@Paul Kubb:

>>if this applied to xaf soon or later, could it improve scalabiliy of the total xaf as well?

Which XAF supported platform and scenarios are you referring to? If we talk about the new ASP.NET Core Data Service, it may indeed improve its throughput under a high load. Refer to the www.carlrippon.com/scalable-and-performant-asp-net-core-web-apis-asynchronous-operations article for more information.

@Dmitri Peredera, Aluron:

All XPO methods accept System.Threading.CancellationToken. We do not provide any means for reporting progress, though. I elaborated more on technical reasons at www.devexpress.com/.../faq-xpo-async-await-method-support.

If you are to commit many objects, I support SaiKan's idea. In addition, you can split your large commit into small chunks (create and destroy a separate session for each chunk) and report progress for them. This is a best practice to improve performance of large commits regardless of the parallel execution.

22 October, 2018
Anthony Geiser

Hi Dennis,

Should we use a ThreadSafeDataLayer to use async/await XPO methods?

27 November, 2018
Uriah (DevExpress Support)

Hi Anthony,

In general, the requirement to use the ThreadSafeDataLayer remains the same as if synchronous operations were used in the same context. If the existing code works with the SimpleDataLayer and you just change it to use asynchronous methods, you can continue using the SimpleDataLayer.

The only thing that should be avoided is the parallel execution of two asynchronous operations in the context of one Session instance. Use the await operator if you need to call an asynchronous method several times.

await session.DoSomethingAsync();

await session.DoSomethingAsync();

29 November, 2018

Please login or register to post comments.