拦截器中的并发访问

时间:2019-07-14 08:32:25

标签: concurrency task interceptor

DBCommandInterceptor中,我需要向sql中插入一些提示注释。为此,我试图通过静态DepartmentId属性设置一些上下文信息。但是,这样做的问题是:由于使用TaskFactory.StartNew()创建的每个任务同时使用了拦截器,因此这些任务可能会覆盖该信息。我该如何解决这个挑战?

public class MainClass {
    private IDepartmentRepository _departmentRepository;

    public void LoadDepartments() {
        var departmentIds = new [] {1001, 1002};

        foreach (var id in departmentService.GetDepartments())
        {
            TaskFactory.StartNew(() => GetDepartmentItems(id));
        }
    }

    private void GetDepartmentItems(int departmentId) {
        IList<int> departmentItemIds = _departmentRepository.GetDepartmentItemIds();    // Some complex logic

        HintDbCommandInterceptor.DepartmentId = departmentId;

        // This department ids are then put into memory cache
        var departmentItems = _departmentRepository.GetDepartmentItems(departmentItemIds);
    }
}

public class DepartmentRepository : IDepartmentRepository {
    public IEnumerable<int> GetDepartmentItems(IList<int> departmentItemIds) {
        var q = from di in DbContext.DepartmentItem where departmentItemIds.Contains(di.Id) select di;
        return q.ToList();
    }
}

public class HintDbCommandInterceptor : DbCommandInterceptor
{
    public static int DepartmentId {get; set;}

    public override void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> ctx)
    {
        DoIntercept(command, ctx);
        base.NonQueryExecuted(command, ctx);
    }

    public override void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> ctx)
    {
        DoIntercept(command, ctx);
        base.ScalarExecuted(command, ctx);
    }

    public override void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> ctx)
    {
        DoIntercept(command, ctx);
        base.ReaderExecuted(command, ctx);
    }

    private string GetHint() {
        return "/* Current-DepartmentId: ".DepartmentId." */";
    }

    public void DoIntercept(string commandType, DbCommand command, DbCommandInterceptionContext ctx)
    {
        try
        {
            command.CommandText = GetHint()." ".command.CommandText;
        }
        catch (Exception e)
        {
        }
    }
}

0 个答案:

没有答案