简体   繁体   中英

FromResult or IServiceScopeFactory in Blazor server-side

So I've been injecting IServiceScopeFactory to my pages to use it's scope when getting my data through EF Core. But yesterday I stumbled upon somebody using Task.FromResult when calling the database. Is one preferred over the other and if so why?

Thank you in advance!

Ex Task.FromResult

//In code behind
[Inject]
IMyService myService { get; set; }

protected void GetSomeData()
{
   var someData = await myServie.GetSomeData(); 
}

//From serviceClass
public async Task<List<SomeData>> GetSomeData(int id)
{
   return await Task.FromResult(db.SomeTable.Where(x => x.Id == qualifierVersionId).AsEnumerable());
}

Ex

//In code behind
[Inject]
IServiceScopeFactory ScopeFactory { get; set; }
protected void GetSomeData()
{
   using (var serviceScope = ScopeFactory.CreateScope())
   {
       var myService = serviceScope.ServiceProvider.GetService<IMyService>();

       var someData = await myServie.GetSomeData(); 
   }
}

//From serviceClass
public async Task<List<SomeData>> GetSomeData(int id)
{
   return await db.SomeTable.Where(x => x.Id == id).ToListAsync();
}

Edit (because the questions of why I want to know which way to go)

I need to use one or the other because when using Server side Blazor the lifespan makes a Scoop behave like a Singleton. So if I for instance call return await db.SomeTable.Where(x => x.Id == id).ToListAsync(); without the IServiceScopeFactory it will live until you close the website. So this creates an error: 'A second operation started on this context before a previous operation completed.'.

You can't compare the two as they don't have anything in common.

Task.FromResult just creates a task that's completed successfully with the specified result. I believe one of the main use cases for using Task.FromResult is when you're implementing an async interface but your implementation is synchronous, as in the example above. This is not really a good idea on DB calls as they could take a long time.

I'm not sure why you're using the IServiceScopeFactory above. If it's so that the service you're requesting is scoped to the lifetime of the component you're requesting it in then there is a better way.

public class MyComponent : OwningComponentBase<IMyService>
{
    protected void GetSomeData(int id)
    {
        var someData = await Service.GetSomeData(id);
    }
}

public class MyService : IMyService
{
    public async Task<List<SomeData>> GetSomeData(int id)
    {
        return await db.SomeTable.Where(x => x.Id == id).ToListAsync();
    }
}

By using OwningComponentBase a service scope is created for you under the hood and the service is exposed by the base component via the Service property. I'vewritten a blog post on it if you want to know more.

I'm not sure I understand why you compare Task.FromResult with IServiceScopeFactory, and any way, it is not clear why you use IServiceScopeFactory in your code.

You should not await a call to Task.FromResult. This method is used when the result is immediately known, and no processing is required, so why await it. Database calls should be used asynchronously, The call may require long and complicated processes. and should never be used with Task.FromResult

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM