问题
I have configured ninject in wep api as below. I have created two kernel objects, one in request scope and another in thread scope:
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);
Here new Kernel is a class for creating thread scope 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;
}
}
}
Now I have created two tasks in below action methods:
[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; }
}
The above code will create two thread and call the method 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();
}
Thread code:
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());
}
}
What I observed is: when SaveChanges
is called in one thread and I refresh the database no records are effected with status 11. When second thread done its execution then the records gets effected.
My question is,
1) does InThreadScope()
creates one dbcontext
per thread or multiple dbcontext
?
2) Is there any transaction maintained by Task.WaitAll
so that all the threads execution will be committed at once
Please suggest, if I am missing anything.
来源:https://stackoverflow.com/questions/51880046/does-thread-scope-in-ninject-creates-new-dbcontext-on-every-thread-call