Fred
Fred

Reputation: 1221

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.'.

Upvotes: 1

Views: 439

Answers (1)

Chris Sainty
Chris Sainty

Reputation: 8531

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've written a blog post on it if you want to know more.

Upvotes: 1

Related Questions