Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 批量更新行值ASP.NET Core C控制台应用程序_C#_Sql Server_Asp.net Core - Fatal编程技术网

C# 批量更新行值ASP.NET Core C控制台应用程序

C# 批量更新行值ASP.NET Core C控制台应用程序,c#,sql-server,asp.net-core,C#,Sql Server,Asp.net Core,我有一个控制台应用程序,可以从instagram url获取json数据,如下所示: 因此,我需要查询所有具有非空instagram用户名的行,然后每行通过公共api进行IG查找,以获取IG帐户id并更新相应的db行 我有两段sql代码,它从表中进行全选,如果InstagramIds为空,则输出它们,另一个查询是根据instagram用户名更新instagram ID 如何对数据库中的每个InstagramMuserName进行批量搜索和更新,并将所有相应的instagram ID添加到数据库中

我有一个控制台应用程序,可以从instagram url获取json数据,如下所示:

因此,我需要查询所有具有非空instagram用户名的行,然后每行通过公共api进行IG查找,以获取IG帐户id并更新相应的db行

我有两段sql代码,它从表中进行全选,如果InstagramIds为空,则输出它们,另一个查询是根据instagram用户名更新instagram ID

如何对数据库中的每个InstagramMuserName进行批量搜索和更新,并将所有相应的instagram ID添加到数据库中

public static async Task<InstagramUser> ScrapeInstagram(string url)
    {
        using (var client = new HttpClient())
        {
            var response = await client.GetAsync(url);
            if (response.IsSuccessStatusCode)
            {
                // create html document
                var htmlBody = await response.Content.ReadAsStringAsync();
                var htmlDocument = new HtmlDocument();
                htmlDocument.LoadHtml(htmlBody);

                // select script tags
                var scripts = htmlDocument.DocumentNode.SelectNodes("/html/body/script");

                // preprocess result
                var uselessString = "window._sharedData = ";
                var scriptInnerText = scripts[0].InnerText
                    .Substring(uselessString.Length)
                    .Replace(";", "");

                // serialize objects and fetch the user data
                dynamic jsonStuff = JObject.Parse(scriptInnerText);
                dynamic userProfile = jsonStuff["entry_data"]["ProfilePage"][0]["graphql"]["user"];

                //Update database query 
                string connectionString = @"Server=MyProject-dev-db.cothtpanmcn7.ap-southeast-2.rds.amazonaws.com;Database=UserApp;User Id=testadmin;Password=test123;MultipleActiveResultSets=true;Trusted_Connection=False;";

                using (SqlConnection con = new SqlConnection(connectionString))
                {
                    //select all users with null value 
                    SqlCommand select = new SqlCommand("Select * from ApplicationUser where InstagramId is null");

                    //Updates InstagramID based from user input of instagramUsername
                    SqlCommand cmd = new SqlCommand("Update ApplicationUser Set InstagramId = '" + userProfile.id + "'" + "where Instagram =  '" + userProfile.username + "'", con);
                    cmd.Connection.Open();
                    cmd.ExecuteNonQuery();


                }

                // create an InstagramUser
                var instagramUser = new InstagramUser
                {
                    FullName = userProfile.full_name,
                    FollowerCount = userProfile.edge_followed_by.count,
                    FollowingCount = userProfile.edge_follow.count,
                    Id = userProfile.id,
                    url = url
                };
                return instagramUser;
            }
            else
            {
                throw new Exception($"Something wrong happened {response.StatusCode} - {response.ReasonPhrase} - {response.RequestMessage}");
            }
        }
    }

你可以这样做

获取所有没有InstagramId的用户 循环遍历用户,并调用API 将数据从API映射到ApplicationUser 在SQL Server中创建临时表 在我的示例中,使用大容量复制在临时表中插入数据 使用临时表与ApplicationUser连接以更新大量行。 有点伪代码:

var applicationUsers = await GetAllApplicationUsersWithoutInstagramId(); // Get the records from the database
foreach(var user in applicationUsers)
{
   var instagramInfo = await GetInstagramInfo(user ); // Get the data from the API
   u.InstagramId = instagramInfo.Id;
   // Map other properties
});


using (SqlConnection con = new SqlConnection(connectionString))
{
   await con.OpenAsync();
   var transaction = con.BeginTransaction();
   // Create a temp table
   var cmd = new SqlCommand("CREATE #NewData(InstagramUsername NVARCHAR(255) NOT NULL PRIMARY KEY, InstagramId BIGINT NOT NULL  /*Other columns*/)", con, transaction);
   await cmd.ExecuteNonQueryAsycn();
   
   // Create a data table to use with the SqlBulkCopy
   var table = new DataTable();
   foreach (var applicationUser in applicationUsers)
   {
       var row = table.NewRow();
       row["InstagramUsername"] = applicationUser.Instagram;
       row["InstagramId "] = applicationUser.InstagramId;
       /*Other columns*/
       table.Rows.Add(row);
   }

   // Bulk insert the new data into the temp table
   using var bulkCopy = new SqlBulkCopy(con, SqlBulkCopyOptions.Default, transaction)
   {
      DestinationTableName = "#NewData", 
      BulkCopyTimeout = 3600 // 1 hour 
   };
   await bulkCopy.WriteToServerAsync(table);
   
   // Perform the update
   cmd = new SqlCommand(@"
    UPDATE au 
       SET au.InstagramId = nd.InstagramId 
       /*Other columns*/
    FROM ApplicationUser  au
    INNER JOIN #NewData nd on au.Instagram = nd.InstagramUsername
   ", con,transaction);   
   await cmd.ExecuteNonQueryAsync();
   
   await transaction.CommitAsync();
}

没有大容量搜索和大容量更新,唯一的大容量操作是大容量插入。因此,我每次都必须进行单独的搜索才能更新表中的每一行?您可以同时更新多行,但不是在批量操作中。我知道如何获取所有为空的Instagramid,但我不知道如何循环并同时执行搜索以更新所有Instagramid。如果从SQL角度执行此操作,您可能不想循环。您将使用一个更新和一个新值连接到您的数据。在psuedo术语中:UPDATE I SET instagramID=ND.NewID FROM dbo.Instagram I JOIN NewData ND ON{Some JOIN子句};它如何知道哪个instagram用户名映射到哪个Id?您可以通过使用表的主键或instagram列的用户来做到这一点,请参阅updated answer.Parallel.ForEach用于数据并行,因此在任何情况下它都是完全无用的。并行运行8个SqlBulkCopy操作很容易导致1/8的性能,因为它们彼此冲突,试图在网络上使用相同的带宽,在服务器上使用相同的磁盘IO。最后,所有连接都会尝试更新同一个目标,彼此阻塞。有没有一种方法可以做到这一点而不创建新表?这个控制台应用程序只会使用几次,所以我不想为此更改数据库reason@PanagiotisKanavosParalle.ForEach并没有在SQL Server上进行任何数据访问,它只是在那里处理对外部api的调用。