【问题标题】:C# webapi async context issueC# webapi 异步上下文问题
【发布时间】:2017-09-04 04:10:48
【问题描述】:

我有两个控制台应用程序同时调用我的 webapi,我在控制台应用程序中返回来自我的 api 的以下响应:

在前一个异步操作完成之前,在此上下文上启动了第二个操作。使用 'await' 确保在此上下文上调用另一个方法之前已完成任何异步操作。不保证任何实例成员都是线程安全的。

所以他们同时调用了我的 webapi,然后 webapi 内部的东西无法处理这 2 个异步调用,所以返回了这个错误。

我检查了 webapi 项目上的所有代码,所有方法都是异步的并等待,所以我不明白为什么会这样。

这是 webapi 的代码。

控制器:

public class FederationsController : ApiController
{
    private readonly IFederationRepository _federationRepository;

    public FederationsController(IFederationRepository federationRepository)
    {
        _federationRepository = federationRepository;
    }

    [HttpGet]
    [Route("federations", Name = "GetFederations")]
    public async Task<IHttpActionResult> GetFederations()
    {
        var federations = await _federationRepository.GetAllAsync();
        return Ok(federations.ToModel());
    }
}

存储库

 public class FederationRepository : IFederationRepository, IDisposable
{
    private Models.DataAccessLayer.CompetitionContext _db = new CompetitionContext();

    #region IQueryable
    private IQueryable<Models.Entities.Federation> FederationWithEntities()
    {
        return _db.Federations.Include(x => x.Clubs)
                              .Where(x => !x.DeletedAt.HasValue && x.Clubs.Any(y => !y.DeletedAt.HasValue));
    }
    #endregion IQueryable

public async Task<IEnumerable<Models.Entities.Federation>> GetAllAsync()
    {
        return await FederationWithEntities().ToListAsync();
    }
}

映射器

public static class FederationMapper
{
    public static List<Federation> ToModel(this IEnumerable<Models.Entities.Federation> federations)
    {
        if (federations == null) return new List<Federation>();
        return federations.Select(federation => federation.ToModel()).ToList();
    }

    public static Federation ToModel(this Models.Entities.Federation federation)
    {
        return new Federation()
        {
            Name = federation.Name,
            FederationCode = federation.FederationCode,
            CreatedAt = federation.CreatedAt,
            UpdatedAt = federation.UpdatedAt
        };
    }
}

DbContext

public class CompetitionContext : DbContext
{
    public CompetitionContext() : base("ContextName")
    {
    }

    public DbSet<Federation> Federations { get; set; }
}

UnityConfig

 public static class UnityConfig
{
    public static void RegisterComponents()
    {
        var container = new UnityContainer();
        container.RegisterType<IFederationRepository, FederationRepository>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}

感谢您的所有建议/帮助。

【问题讨论】:

  • 我会检查是否有什么东西导致你的统一注册被搞砸了,它就像一个单一的 IFederationRepository 在请求之间共享。尝试在统一注册中显式设置TransientLifetimeManger,看看它是否有任何改变。
  • @ScottChamberlain 我试过这个容器。RegisterType(new HierarchicalLifetimeManager());但如果这就是你的意思,那也没有解决问题?
  • HierarchicalLifetimeManager 是绝对错误的管理器,每次解析都需要一个新的类副本。你需要一个TransientLifetimeManger
  • 缺少一些东西,只有在同时执行两个异步方法而不在两个异步方法上都使用 await 时才会引发异常。请为您的异常添加堆栈跟踪,我怀疑您的存储库不是问题(即使您应该像 Simon 在他的回答中所说的那样重写它)。
  • @FedericoDipuma 谢谢你解决了这个问题我再次检查了我的异常跟踪,发现在每次向 api 请求之前,他还做了一些安全措施,这也得到了一个 dbcontext。我用 using(var db = new CompetitionContext()) 更改了所有方法,现在它运行得非常好。

标签: c# entity-framework asynchronous asp.net-web-api


【解决方案1】:

在您的存储库中,您正在创建一个 CompetitionContext 并重用它。我假设 IoC 设置将存储库注册为某种单一实例,因此每次都使用同一个存储库。如果是这种情况,您应该为每个方法调用创建一个新的 CompetitionContext。

另外,可能应该确保使用 using 语句将其关闭。

我也不清楚您的代码 sn-ps 为什么要从该 FederationWithEntities 方法返回 IQueryable,您还有其他正在使用它的东西吗?

无论如何,我可能会将 GetAllMethod 更改为这样的:

public async Task<IEnumerable<Models.Entities.Federation>> GetAllAsync()
{
  using (Models.DataAccessLayer.CompetitionContext _db = new CompetitionContext())
  {
     return _db.Federations.Include(x => x.Clubs)
                           .Where(x => !x.DeletedAt.HasValue && x.Clubs.Any(y => !y.DeletedAt.HasValue))
                           .ToListAsync();
  }
}

【讨论】:

  • 或者确保上下文是每个请求的。
  • RegisterType 应该默认创建一个新的FederationRepository 每次调用控制器的构造函数,并且每次请求都会调用一次构造函数。每个新的FederationRepository 都会创建一个新的CompetitionContext
  • 我尝试了这个解决方案,但它并没有解决问题。
猜你喜欢
  • 1970-01-01
  • 2014-01-03
  • 2015-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多