ninject中的线程范围是否在每个线程调用上创建新的dbcontext

时间:2018-08-16 14:57:38

标签: multithreading entity-framework scope ninject

我在wep api中配置了ninject,如下所示。我创建了两个内核对象,一个在请求范围内,另一个在线程范围内:

var requestKernel = new StandardKernel();
requestKernel.Bind<IGlobalDbContext>().ToConstructor(ctx => new GlobalDbContext(Configuration.GlobalDbContext)).InRequestScope();

var threadKernel = new StandardKernel();
RegisterServices(threadKernel);
threadKernel.Bind<IGlobalDbContext>().ToConstructor(ctx => new GlobalDbContext(Configuration.GlobalDbContext)).InThreadScope();
new Kernel(threadKernel);

这里的新内核是用于创建线程范围DBContext的类:

public class Kernel
{
    private static StandardKernel _kernel = null;

    public Kernel(StandardKernel kernel)
    {
        if (_kernel == null)
        {
            _kernel = kernel;
        }
    }

    public static IKernel GetKernel
    {
        get
        {
            return _kernel;
        }
    }
}

现在,我在以下操作方法中创建了两个任务:

[HttpPost]
public void RunThreadrequest()
{
    ThreadFactory threadFactory = new ThreadFactory();
    DateTime fromDate = Convert.ToDateTime("2018-05-01");
    DateTime toDate = Convert.ToDateTime("2018-05-31");
    List<int> orders = _orderManager.All().Where(o => o.IsActive && (o.DeliveryDate >= fromDate && o.DeliveryDate <= toDate)).Select(o => (int)o.Id).ToList();
    int length = 2;
    int i = 0;
    int startIndex = 0;
    int endIndex = orders[0] - 1;
    do
    {
        startIndex = endIndex + 1;
        endIndex = startIndex + 5;
        OrderIndex ordIndexObj = new OrderIndex { StartIndex = startIndex, EndIndex = endIndex };
        threadFactory.CreateThread((ordIndex) =>
        {
            ParameterConfigurationController controller =  (ParameterConfigurationController)(Kernel.GetKernel.GetService(typeof(ParameterConfigurationController)));
            controller.UpdateOrders(((OrderIndex)ordIndex).StartIndex, ((OrderIndex)ordIndex).EndIndex);
        }, ordIndexObj);
        i++;
    } while (i < length);
    threadFactory.Run();
}

public struct OrderIndex
{
    public int StartIndex { get; set; }
    public int EndIndex { get; set; }
    public int ThreadId { get; set; }
    public int Index { get; set; }
}

上面的代码将创建两个线程并调用方法UpdateOrders

public void UpdateOrders(int startIndex, int lastIndex)
{
    var orders = _orderManager.All().Where(o => o.Id >= startIndex && o.Id <= lastIndex).ToList();
    foreach (Order order in orders)
    {
        order.StatusId = 11;
    }      
    _orderManager.SaveChanges();
}

线程代码:

class ThreadFactory
{
    private List<Task> threads = new List<Task>();
    private CancellationTokenSource source = new CancellationTokenSource();
    private CancellationToken token;
    public ThreadFactory()
    {
        token = source.Token;
    }

    public void CreateThread(Action<object> action, OrderIndex ordObj)
    {
        if (token.IsCancellationRequested)
            token.ThrowIfCancellationRequested();
        Task task = Task.Factory.StartNew(action, ordObj, token);
        threads.Add(task);
    }

    public void Run()
    {
        Task.WaitAll(this.threads.ToArray());
    }
}

我观察到的是:当在一个线程中调用SaveChanges并刷新数据库时,状态为11的记录将不受影响。当第二个线程完成其执行后,记录将生效。

我的问题是,

1)InThreadScope()是每个线程创建一个dbcontext还是多个dbcontext

2)Task.WaitAll是否维护任何事务,以便所有线程执行都将立即提交

如果我有任何遗漏,请提出建议。

0 个答案:

没有答案