在线程内调用存储过程以更新多个记录

时间:2012-04-12 10:35:35

标签: asp.net multithreading parallel-processing task-parallel-library procedure

我正在尝试为各种独特实体设置calla存储过程。单个实体的存储过程大约需要33秒。所以我决定用线程来调用它。

以下是我所做的一些试验:

public bool ExecuteTaxRateLinkingParallel(int mapID, int createdBy)
{
    try
    {
        int snapshotID = (int)(HttpContext.Current.Session[GlobalConstant.snapShotID]);
        List<TaxEntity> taxEntities = new List<TaxEntity>();
        List<Task> tasks = new List<Task>();
        using (var ctx = new TopazDbContainer())
        {
            taxEntities = ctx.TaxEntities.AsParallel().Where(t => t.IsActive == true).ToList<TaxEntity>();
        }

        Parallel.ForEach<TaxEntity>(taxEntities, (entity) =>
        {
            //SqlConnection connection; SqlTransaction trans; SqlCommand command;
            // break this into pieces of 5
            var task = Task.Factory.StartNew(() =>
            {
                using (var pctx = new TopazDbContainer())
                {
                    try
                    {
                        int taxEntityID = entity.TaxEntityID;
                        pctx.CommandTimeout = 5000;
                        //string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["TOPAZDBConnectionStringParallel"].ConnectionString;
                        //connection = new SqlConnection(connectionString);
                        //command = new SqlCommand("dbo.[Usp_TaxRatesLinkingParallel]", connection);
                        //trans = connection.BeginTransaction();
                        //command.CommandType = CommandType.StoredProcedure;
                        //command.Parameters.AddWithValue("@MapID", mapID);
                        //command.Parameters.AddWithValue("@UserID", createdBy);
                        //command.Parameters.AddWithValue("@TaxEntityID", taxEntityID);
                        //command.Parameters.AddWithValue("@SnapshotID", snapshotID);
                        //connection.Open();
                        //command.CommandTimeout = 5000;
                        //command.ExecuteReader().AsParallel();

                        pctx.ContextOptions.LazyLoadingEnabled = true;

                        //pctx.ExecuteStoreCommand("Exec [Usp_TaxRatesLinkingParallel] @MapID={0},@UserID={1},@TaxEntityID={2},@SnapshotID{3}", new SqlParameter("MapID", mapID), new SqlParameter("UserID", createdBy), new SqlParameter("TaxEntityID", taxEntityID), new SqlParameter("SnapshotID", snapshotID));
                        var param = new DbParameter[] { new SqlParameter("UserID", createdBy), new SqlParameter("TaxEntityID", taxEntityID), new SqlParameter("SnapshotID", snapshotID) };
                        pctx.ExecuteStoreCommand("Exec [Usp_TaxRatesLinkingParallel] @MapID,@UserID,@TaxEntityID,@SnapshotID", param);

                        //var result = output.FirstOrDefault();
                    }
                    catch (TaskCanceledException tx)
                    {
                    }
                    catch (Exception e)
                    {
                    }
                    finally
                    {
                        pctx.SaveChanges();
                        pctx.Connection.Close();
                    }
                }
            }, TaskCreationOptions.PreferFairness);

            tasks.Add(task);

            try
            {
                Task.WaitAll(tasks.ToArray());
            }
            catch (AggregateException ae)
            {
                ae.Handle((x) =>
                {
                    if (x is UnauthorizedAccessException)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                });
            }
            catch (Exception ex)
            {
                throw ex;
            }
        });

        return true;
    }
    catch (Exception ex)
    {
        TopazErrorLogs.AddTopazErrorLogBL(ex, 1, 1);
        throw new TopazCustomException(GlobalConstant.errorMessage);
    }
}

对于上述某些语句,SP似乎运行正常,但是当我从应用程序或后端检查时,记录没有得到更新。

需要帮助!

2 个答案:

答案 0 :(得分:1)

如果您还没有使用.NET 4.5,则可以使用这些扩展方法执行命令async。

using System.Diagnostics.Contracts;
using System.Threading.Tasks;
using System.Xml;

namespace System.Data.SqlClient
{
    public static class SqlCommandExtensions
    {
        public static Task<SqlDataReader> ExecuteReaderAsync(this SqlCommand command)
        {
            Contract.Requires(command != null);
            return ExecuteReaderAsync(command, null);
        }

        public static Task<SqlDataReader> ExecuteReaderAsync(this SqlCommand command, object state)
        {
            Contract.Requires(command != null);
            return Task.Factory.FromAsync<SqlDataReader>(command.BeginExecuteReader, command.EndExecuteReader, state);
        }

        public static Task<XmlReader> ExecuteReaderXmlAsync(this SqlCommand command)
        {
            Contract.Requires(command != null);
            return ExecuteReaderXmlAsync(command, null);
        }

        public static Task<XmlReader> ExecuteReaderXmlAsync(this SqlCommand command, object state)
        {
            Contract.Requires(command != null);
            return Task.Factory.FromAsync<XmlReader>(command.BeginExecuteXmlReader, command.EndExecuteXmlReader, state);
        }

        public static Task<int> ExecuteNonQueryAsync(this SqlCommand command)
        {
            Contract.Requires(command != null);
            return ExecuteNonQueryAsync(command, null);
        }

        public static Task<int> ExecuteNonQueryAsync(this SqlCommand command, object state)
        {
            Contract.Requires(command != null);
            return Task.Factory.FromAsync<int>(command.BeginExecuteNonQuery, command.EndExecuteNonQuery, state);
        }
    }
}

答案 1 :(得分:0)

这不是您在此处执行的异步数据库查询。请看一下:

Asynchronous Database Calls With Task-based Asynchronous Programming Model (TAP) in ASP.NET MVC 4

以下是使用新的async / await功能进行异步数据库调用的示例:

public async Task<IEnumerable<Car>> GetCarsAsync() {

    var connectionString = 
        ConfigurationManager.ConnectionStrings["CarGalleryConnStr"].ConnectionString;

    var asyncConnectionString = new SqlConnectionStringBuilder(connectionString) {
        AsynchronousProcessing = true
    }.ToString();

    using (var conn = new SqlConnection(asyncConnectionString)) {
        using (var cmd = new SqlCommand()) {

            cmd.Connection = conn;
            cmd.CommandText = selectStatement;
            cmd.CommandType = CommandType.Text;

            conn.Open();

            using (var reader = await cmd.ExecuteReaderAsync()) {

                return reader.Select(r => carBuilder(r)).ToList();
            }
        }
    }
}

您可以在博文中找到详细信息。