c# - How to make async with linq -


i'm trying make first web application asp.net mvc including remote database linq. i'm using default template mvc, i've remade code in accountcontroller implement register users using linq, , i'm interesting async. possible handle linq async? , if yes, show me please example how that, helpful me. here's example of registration via linq:

[allowanonymous] public actionresult register() {     return view(); }  // // post: /account/register [httppost] [allowanonymous] [validateantiforgerytoken] public actionresult register(registerviewmodel model) {     if (modelstate.isvalid)     {         using (databaseclassdatacontext dc = new databaseclassdatacontext())         {             users tbusers = new users();             tbusers.login = model.login;             tbusers.name = model.name;             tbusers.surname = model.surname;             tbusers.password = model.password;             tbusers.e_mail = model.email;             tbusers.knowledge = model.knowledge;             dc.users.insertonsubmit(tbusers);             dc.submitchanges();              modelstate.clear();             viewbag.message = "successfully registration done";         }     }      // if got far, failed, redisplay form     return view(model); } 

let's @ first action first:

[allowanonymous] public actionresult register() {   return view(); } 

well, there's nothing here delay current thread, there's no benefit in doing asynchronously, best thing leave 1 alone.

now, let's @ second action. contains:

dc.submitchanges(); 

that indeed block current thread while changes sent database. won't big hit, somewhere might benefit using asynchronous code, because it's darn easy these days.

first change signature:

public async task<actionresult> register(registerviewmodel model) 

if compile work, you'll warning:

 async method lacks 'await' operators , run synchronously. consider using 'await' operator await non-blocking api calls, or 'await task.run(...)' cpu-bound work on background thread. 

but we've done 2 things:

  1. changed returning actionresult returning task<actionresult>.
  2. used async mean can return view(model); , gets turned code returns task<actionresult> when run run code in original method.

but we've not gained anything. instead of dc.submitchanges() we'll use dc.submitchangesasync().

this assuming exists, depend on data provider. more on in bit.

if exist instead of returning void or value t return task or task<t>.

we could write code handle task ourselves, easiest thing is:

await dc.submitchangesasync(); 

now method have 1 returns task<action> when run (mvc handle bit us) execute code far await. release thread running code other things. after submitchangesasync has done job, execution of method resumes @ point.

similarly turn method like:

var somelist = somequery.tolist(); 

into:

var somelist = await somequery.tolistasync(); 

now, said, depends on methods result in database access having async version. if there no submitchangesasync() either have give on approach (boo!) or have write own implementation (not trivial).

the current version of entityframework provides following:

allasync anyasync averageasync containsasync countasync firstasync firstordefaultasync foreachasync loadasync longcountasync maxasync minasync singleasync singleordefaultasync sumasync toarrayasync todictionaryasync tolistasync savechangesasync 

that is, pretty of methods result in actual database access have async version.

if not using provider offers this, moving asynchronous code not easy; it'll involve more can put quick answer well.

one final caveat. have async method single await , await tail-call:

public async task<list<int>> getlist(int typeid) {   if(typeid < 1)     throw new argumentoutofrangeexception();   return await (from stuff in place stuff.typeid == typeid select stuff).tolistasync(); } 

here should not use async , await @ all, because creating task result in single task being awaited on, , await complicates things behind scenes no reason. here should return task:

public task<list<int>> getlist(int typeid) {   if(typeid < 1)     throw new argumentoutofrangeexception();   return (from stuff in place stuff.typeid == typeid select stuff).tolistasync(); } 

but note looks tail call inside using block not tail call, because implicitly dispose() @ end of using, can't simplify such calls in way.

you can though simplify cases there different possible tail calls, long every path either such call, or throws exception:

public async task<list<int>> getlist(int? typeid) {   if(!typeid.hasvalue)     throw new argumentnullexception();   if(typeid.value < 0)     return await (from stuff in place).tolistasync();   return await (from stuff in place stuff.typeid == typeid select stuff).tolistasync(); } 

can become:

public task<list<int>> getlist(int? typeid) {   if(!typeid.hasvalue)     throw new argumentnullexception();   if(typeid.value < 0)     return (from stuff in place).tolistasync();   return (from stuff in place stuff.typeid == typeid select stuff).tolistasync(); } 

Comments

Popular posts from this blog

c++ - Difference between pre and post decrement in recursive function argument -

php - Nothing but 'run(); ' when browsing to my local project, how do I fix this? -

php - How can I echo out this array? -