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

16 October 2018

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. 

21 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
Nikita Grigoryev

Is there a way to make async call by session.ExecuteQueryWithMetadata and session.ExecuteQuery methods? Couldn't find any and that's my use case - I'm not loading persistent objects but rather using ORM features for building sql requests independent from database.

25 January, 2019
Dennis (DevExpress Support)

@Nikita Grigoryev:

Not in v18.2. However, nothing prevents you from wrapping these method calls into the Task.Run method manually, if required. This is already supported in v19.1.

For more information, see "Do these new Task-based APIs provide notifications..." point on asynchronous support at the ADO.NET level in our FAQ: www.devexpress.com/.../faq-xpo-async-await-method-support.

25 January, 2019
Nikita Grigoryev

>Not in v18.2. However, nothing prevents you from wrapping these method calls into the Task.Run method manually, if required. This is already supported in v19.1.

I don't think it's the same as utilizing I/O completion thread since Task.Run creates threads and ado.net async method does not allocate any additional threads.

>This is already supported in v19.1.

Is 19.1 supports ado.net async functions or database requests are wrapped in Task.Run?

27 January, 2019
Dennis (DevExpress Support)

@Nikita Grigoryev: My apologies for not being clear enough. In v18.2, you can use Task.Run as a workaround (yes, we are aware of its behavior) while v19.1 already supports ADO.NET async functions natively. For more information on XPO 2019 plans, refer to the community.devexpress.com/.../express-persistent-objects-2019-roadmap.aspx post.

28 January, 2019
Dennis (DevExpress Support)

@Nikita Grigoryev: Feel free to test our enhanced async/await method support in v19.1: community.devexpress.com/.../eXpress-Persistent-Objects-Early-Access-Preview-v19-1.aspx

19 March, 2019
XPO Team Blog

Thanks to great user feedback, we had a successful release with several major new features. In this post, I will highlight a number of smaller, but useful additions to our ORM and its associated learning materials.

19 April, 2019

Please login or register to post comments.