将并行或任务与web服务和数据库连接一起使用

本文关键字:数据库连接 一起 服务 web 并行 任务 | 更新日期: 2023-09-27 18:06:06

解释
我有一个场景,我有1000个客户,他们的信息存储在不同的区域,我需要从一个地方检索他们的交易他们的余额来自另一个,他们的信息来自本地源

前2个(交易和余额(使用Web服务,本地信息是一个正常的数据库SqlConnection

在运行每个客户之前,我会检索余额列表,因为每个客户都有一个余额条目,但每个客户必须检索客户交易,其余的计算取决于

我需要了解每个客户,并在他们的账户上做一些事情,比如如果交易符合某些标准,就发放奖金或扣除,每月发放免费积分等等。
需要对帐户执行的每一项操作都需要一个新的数据库或web调用来更新该资源

所以代码看起来像这样(psuedo(

var Clients = getfromDB();
var Balances = webservicecall.getbalances();
var clientswithbalances = from balance in Balances
                    join customer in Clients on balance.Idnumber equals customer["IdNumber"]
                    orderby Convert.ToInt32(customer["CustomerId"])
                    select new
                    {
                        CustomerId = Convert.ToInt32(customer["CustomerId"]),
                        Name = customer["Name"].ToString(),
                        Idnumber = customer["Idnumber"].ToString(),
                        Balance = Convert.ToDouble(balance.Value, CultureInfo.InvariantCulture)
                    };
foreach (var user in users)
{
   var transactions = webcalltransactions(user.Idnumber);
   //calculations that use more webservices and database calls updates and inserts
}

问题
我尝试了parallel.foreach,但它在Web服务和数据库调用方面出现了问题
做到这一点的最佳方法是什么?

将并行或任务与web服务和数据库连接一起使用

您可以制作一个控制台应用程序来测试这一点,但仅适用于.net 4.5>=。这也可以在其他版本上完成,但需要进行一些更改。

 class Program
        {
            static void Main(string[] args)
            {
                DoStuff().Wait();//As you can see my main thread is blocked if wait is used;
                Console.WriteLine("Done");
                Console.ReadLine();
            }

            public static async Task DoStuff() 
            {
                System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                sw.Start();
                var clientsTask = GetFromDBAsync(); //DON'T await
                var balancesTask = GetBalancesAsync(); //DON'T await
                await Task.WhenAll(clientsTask, balancesTask);//If the implementation is async dose a parallel call the nameing convention is async methods have Async at the end MethodAsync
                var clients = clientsTask.Result;
                var balances = balancesTask.Result;
                var users = Enumerable.Range(clients, balances).Select(i=>new { IdNumber = i }); // I am mocking your query so you can see what is happening
                var usersTasks = users.Select(user => GetClientAsync(user.IdNumber)).ToArray();
                var userServerData = await Task.WhenAll(usersTasks);//You can do Task.WaitAll(usersTasks) if your method can't be async but this will block you main thread and can be buggy ;
                foreach (var user in userServerData)
                {
                    Console.WriteLine(user);
                }
                sw.Stop();
                Console.WriteLine("Total time {0}", sw.ElapsedMilliseconds);//Total time is close to 2s rather then 22s if everething is sync;
            }
            public static Task<int> GetFromDBAsync()
            {
                return Task.Delay(1000).ContinueWith(t => 0);
            }
            public static Task<int> GetBalancesAsync()
            {
                return Task.Delay(1000).ContinueWith(t => 20);
            }
            public static Task<int> GetClientAsync(int clientId) 
            {
                return Task.Delay(1000).ContinueWith(t => clientId);
            }
        }