HierarchicalLifetimeManager并在此上下文异常上调用另一个方法

时间:2018-08-16 08:45:51

标签: c# asp.net-mvc entity-framework-6 unity-container

我正在寻找应该往哪个方向的建议。
我有一个带有寄存器类型的统一容器:

UnityConfig.cs

public static void RegisterTypes(IUnityContainer container)
{
     container.RegisterType<IRepository<ActivityExtendedData>, repository<ActivityExtendedData, IntranetContext>>(new HierarchicalLifetimeManager(), new InjectionConstructor());
}

和基于https://stackoverflow.com/a/46674036

的存储库实现

Repository.cs

public class Repository<TDbSet, TDbContext> : IRepository<TDbSet> where TDbSet : class where TDbContext : DbContext, new()
{
    internal DbContext _context;
    internal DbSet<TDbSet> _dbSet;

    public Repository(DbContext context)
    {
        _context = context;
        _dbSet = _context.Set<TDbSet>();
    }

    public Repository() : this(new TDbContext())
    {
    }

    public Repository(string database = null)
    {
        SetDatabase(database);
    }

    public void SetDatabase(string database)
    {
        var dbConnection = _context.Database.Connection;
        if (string.IsNullOrEmpty(database) || dbConnection.Database == database)
            return;

        if (dbConnection.State == ConnectionState.Closed)
            dbConnection.Open();

        _context.Database.Connection.ChangeDatabase(database);
    }
}

 public virtual async Task<IEnumerable<TDbSet>> Get(
        Expression<Func<TDbSet, bool>> filter = null,
        Func<IQueryable<TDbSet>, IOrderedQueryable<TDbSet>> orderBy = null,
        string includeProperties = "",
        int limit = 1000)
    {
        IQueryable<TDbSet> query = _dbSet;

        if (filter != null)
        {
            query = query.Where(filter);
        }

        foreach (var includeProperty in includeProperties.Split
            (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
        {
            query = query.Include(includeProperty);
        }

        if (orderBy != null)
        {
            return await orderBy(query).Take(limit).ToListAsync();
        }
        else
        {
            return await query.Take(limit).ToListAsync();
        }
    }

由控制器调用:

ActivityController

public class ActivityController : Controller
{
    private readonly IRepository<ActivityExtendedData> _activityRepo;

    public ActivityController(IRepository<ActivityExtendedData> activityRepo)
    {
        _activityRepo = activityRepo;
    }

    [Authorize]
    public async Task<ActionResult> Index(int limit = 100)
    {
        return View(
            await _activityRepo.Get(
                limit: limit,
                orderBy: s => s.OrderByDescending(q => q.DateAdd),
                includeProperties: "Request,Response,User,Other"
            ));
    }

使用上述配置,我收到异常:

  

System.NotSupportedException:在先前的异步操作完成之前,第二个操作在此上下文上启动。使用“ await”来确保在此上下文上调用另一个方法之前,所有异步操作都已完成。不保证任何实例成员都是线程安全的。      [...]      在Intranet.EntityFramework \ DAL \ Repository.cs:row 94中的EntityFramework.DAL.Repository`2.d__8.MoveNext()中      [...]      在Portal.Controllers.ActivityController.d__2.MoveNext()处,通过Intranet.Portal \ Controllers \ ActivityController.cs:row 24

Repository.cs:第94行if (orderBy != null),ActivityController.cs:第24行await _activityRepo.Get( 我不知道如何在Repository()中更改Get()方法,并在其中放置正确的await方法。 所以我修改了 UnityConfig.cs

public static void RegisterTypes(IUnityContainer container)
    {
        container.RegisterType<IntranetContext>(new PerRequestLifetimeManager());
        container.RegisterType<IRepository<ActivityExtendedData>, Repository<ActivityExtendedData, IntranetContext>>(new PerRequestLifetimeManager(), new InjectionConstructor());
    }

可能不需要行container.RegisterType<IntranetContext>(new PerRequestLifetimeManager());
但是现在我需要为每个请求接收新的Context和Repository实例,并且当然不会出现异常。但这是一个好方法吗?

0 个答案:

没有答案