Blazor服务器端的FromResult或IServiceScopeFactory

时间:2019-10-16 06:54:17

标签: c# blazor blazor-server-side

因此,我一直在向页面注入IServiceScopeFactory以便在通过EF Core获取数据时使用它的作用域。 但是昨天我偶然发现有人在调用数据库时使用Task.FromResult。 是一个比另一个更好的选择吗?

提前谢谢!

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();
}

编辑(因为为什么我想知道该走哪条路的问题)

我需要使用其中一个,因为在使用服务器端Blazor时,寿命使Scoop的行为类似于Singleton。因此,如果我例如致电返回等待db.SomeTable.Where(x => x.Id == id).ToListAsync();如果没有IServiceScopeFactory,它将一直存在,直到您关闭网站为止。因此,这会产生一个错误:“在上一个操作完成之前,第二个操作是在此上下文上开始的。”

1 个答案:

答案 0 :(得分:1)

您无法将两者进行比较,因为它们没有共同点。

Task.FromResult只会创建一个成功完成且具有指定结果的任务。我相信使用Task.FromResult的主要用例之一是实现异步接口但实现是同步的,如上例所示。在数据库调用上,这并不是一个好主意,因为它们可能需要很长时间。

我不确定您为什么使用上面的IServiceScopeFactory。如果是这样,那么您所请求的服务的范围仅限于您所请求的组件的生存期,那么有一种更好的方法。

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();
    }
}

通过使用OwningComponentBase,可以在幕后为您创建服务范围,并且基础组件可以通过Service属性来公开该服务。如果您想了解更多,我已经written a blog post在上面。