简体   繁体   English

C# - 无法将数据插入MySQL数据库

[英]C# - Can't insert data into MySQL database

I am making an application where I scrape a certain website. 我正在申请我刮一个网站。 The website has a bunch of players, and I scrape each one of their profile pages. 该网站有很多玩家,我抓了他们的个人资料页面。 Their profile pages contains information like Name, Level, World and Last Login date. 他们的个人资料页面包含姓名,级别,世界和上次登录日期等信息。

So I made an object called Player. 所以我创建了一个名为Player的对象。 And then I add all their data to a list. 然后我将所有数据添加到列表中。

public static List<Player> Players = new List<Player> { };

public class Player
    {
        public string Name { get; set; }
        public string Sex { get; set; }
        public string Vocation { get; set; }
        public int Level { get; set; }
        public int Achievements { get; set; }
        public string World { get; set; }
        public string LastLogin { get; set; }
        public string AccountStatus { get; set; }
        public int OnlineStatus { get; set; }
    }

I add the data like this: 我添加这样的数据:

new Player { Name = playerName, Sex = playerSex, Vocation = playerVocation, Level = playerLevel, Achievements = playerAchievements, World = playerWorld, LastLogin = playerLastLogin, AccountStatus = playerAccountStatus, OnlineStatus = playerOnlineStatus };

I now want to add all the players to my MySQL database, but I cannot seem to understand how to insert the data. 我现在想将所有播放器添加到我的MySQL数据库中,但我似乎无法理解如何插入数据。

I established a connection and I tried to SELECT data and it works fine. 我建立了一个连接,我尝试SELECT数据,它工作正常。 So my connection is not bad. 所以我的联系也不错。 But inserting seems to not work. 但插入似乎不起作用。

Here's my code I add to insert the data into the tables: 这是我添加的代码,用于将数据插入表中:

string connString = "Server=localhost;Port=3306;Database=rookstat;Uid=XXXXXXX;password=XXXXXX;";
MySqlConnection conn = new MySqlConnection(connString);
MySqlCommand command = conn.CreateCommand();

foreach (Player rooker in Players)
{
command.CommandText = "Insert into rookstayers (id, name, sex, vocation, level, achievements, world, lastlogin, accountstatus, onlinestatus) values('', rooker.Name, rooker.Sex, rooker.Vocation, rooker.Level, rooker.Achievements, rooker.World, rooker.LastLogin, rooker.AccountStatus, rooker.OnlineStatus)";
conn.Open();
command.ExecuteNonQuery();
}

conn.Close();

What am I doing wrong? 我究竟做错了什么? I am unsure about the values i insert. 我不确定我插入的值。 Is it supposed to be rooker.Name or what? 它应该是rooker.Name还是什么?

The way in which you build your query creates a single string with your variables names treated as literal strings. 构建查询的方式会创建一个字符串,并将变量名称视为文字字符串。

Instead you need a parameterized query like this 相反,你需要像这样的参数化查询

string connString = "Server=localhost;Port=3306;Database=rookstat;Uid=XXXXXXX;password=XXXXXX;";
using(MySqlConnection conn = new MySqlConnection(connString))
using(MySqlCommand command = conn.CreateCommand())
{
    conn.Open();
    command.CommandText = @"Insert into rookstayers 
             (id, name, sex,   vocation, level, achievements, 
              world, lastlogin, accountstatus, onlinestatus) 
       values('', @name, @sex, @vocation, @level, @Achievements,
              @World, @LastLogin, @AccountStatus, @OnlineStatus)";

    command.Parameters.Add("@name", MySqlDbType.VarChar);
    command.Parameters.Add("@sex", MySqlDbType.VarChar);
    command.Parameters.Add("@vocation", MySqlDbType.VarChar);
    command.Parameters.Add("@level", MySqlDbType.Int32);
    .... and so on for all the parameters placeholders

    command.Prepare();
    foreach (Player rooker in Players)
    {
          command.Parameters["@name"].Value = rooker.Name;
          command.Parameters["@sex"].Value = rooker.Sex;
          command.Parameters["@vocation"].Value = rooker.Vocation;
          command.Parameters["@level"].Value = rooker.Level;

          ... and so on for the other parameters defined
          command.ExecuteNonQuery();
    }
}

In this way, BEFORE entering the loop, you define your sql command and create the parameters in the MySqlCommand Parameters collection without setting the values. 这样,在进入循环之前,您可以定义sql命令并在MySqlCommand Parameters集合中创建参数而不设置值。 And, as suggested below by Mr adding the call to command.Prepare could enhance the performance. 并且,如下所述,Mr先添加了对命令的调用.Prepare可以提高性能。

Inside the loop, for each parameter defined, you could set its value and call the command to execute. 在循环内部,对于定义的每个参数,您可以设置其值并调用命令来执行。

I wish also to point to the using statement that ensure the proper closing and disposing of the objects and the use of Add with proper parameter type set for each parameter instead of AddWithValue. 我还要指出using语句,它确保正确关闭和处理对象,并使用Add为每个参数设置适当的参数类型而不是AddWithValue。 AddWithValue is a shortcut with numerous drawbacks as you can read in this article Can we stop using AddWithValue already? AddWithValue是一个有很多缺点的快捷方式,你可以在本文中看到我们可以停止使用AddWithValue了吗?

A last advice, if this kind of transformations between objects and data happens very often then you should invest a bit of your time to learn to use an ORM tool like Dapper 最后的建议,如果对象和数据之间的这种转换经常发生,那么你应该投入一点时间来学习使用像Dapper这样的ORM工具

EDIT: Looking at your whole code, it seems that you miss an important step in your scraping. 编辑:看看你的整个代码,似乎你错过了一个重要的步骤。 You need to add the Player to your list of Players 您需要将播放器添加到播放器列表中

private async void insertTimer_Tick(object sender, EventArgs e)
{
     if (onlineList.Items.Count > 0)
     {
         for (int i=0; i<onlineList.Items.Count; i++)
         {
              CurrentPlayer = onlineList.Items[i].ToString();
              var playerProfile = await GetData();
              foreach (var row in playerProfile)
              {
                  .... gets player data ....
              }

              // Creates a new Player and add to the insertion list
              Players.Add(new Player 
              { 
                    Name = playerName, 
                    Sex = playerSex, 
                    Vocation = playerVocation, 
                    Level = playerLevel, 
                    Achievements = playerAchievements, 
                    World = playerWorld, 
                    LastLogin = playerLastLogin, 
                    AccountStatus = playerAccountStatus, 
                    OnlineStatus = playerOnlineStatus 
               };
          }

          // And now the inserts goes here
          .......

You are passing string literals to the query, not the variable values: 您将字符串文字传递给查询,而不是变量值:

Try adjusting your query to: 尝试将您的查询调整为:

command.CommandText = "Insert into rookstayers (id, name, sex, vocation) values('', @name, @sex, @vocation)";

Then Parameters.AddWithValue as shown below: 然后是Parameters.AddWithValue ,如下图所示:

command.Parameters.AddWithValue("@name", rooker.Name);
command.Parameters.AddWithValue("@sex", rooker.Sex);
command.Parameters.AddWithValue("@vocation", rooker.Vocation);

etc 等等

This will also help prevent SQL injection. 这也有助于防止SQL注入。

Try the following: 请尝试以下方法:

using(var connection = new MySqlConnection(connectionString)) 
{
    connection.Open();
    using(var command = new MySqlCommand()) 
    {
        command.Connection = connection;
        command.CommandText = @"INSERT INTO rookstayers (name, sex, vocation, level, achievements, world, lastlogin, accountstatus, onlinestatus) VALUES (@name, @sex, @vocation, @level, @achievements, @world, @lastLogin, @accountStatus, @onlineStatus)";
        command.Prepare();

        foreach(var rooker in Players) 
        {
            command.Parameters.Clear();
            command.Parameters.AddWithValue("@name", rooker.Name);
            command.Parameters.AddWithValue("@sex", rooker.Sex);
            command.Parameters.AddWithValue("@vocation", rooker.Vocation);
            command.Parameters.AddWithValue("@level", rooker.Level);
            command.Parameters.AddWithValue("@achievements", rooker.Achievements);
            command.Parameters.AddWithValue("@world", rooker.World);
            command.Parameters.AddWithValue("@lastLogin", rooker.LastLogin);
            command.Parameters.AddWithValue("@accountStatus", rooker.AccountStatus);
            command.Parameters.AddWithValue("@onlineStatus", rooker.OnlineStatus);
            command.ExecuteNonQuery();
        }
    }
}

Note the differences: 注意区别:

  1. Wrapping disposable objects (ie MySQLConnection and MySQLCommand) in using statements. 在using语句中包装一次性对象(即MySQLConnection和MySQLCommand)。
  2. Updated the SQL insert command to use SQL Parameters. 更新了SQL insert命令以使用SQL参数。 In this case, "@name" will be replaced with the value of rooker.Name when the command is executed. 在这种情况下,执行命令时,“@ name”将替换为rooker.Name的值。
  3. Excluded id column in the insert statement as I assume that is the identity column so you don't have to explicitly include that. 插入语句中排除的id列,因为我假设它是标识列,因此您不必明确包含它。
  4. Lastly, use of command.Prepare(). 最后,使用command.Prepare()。 As specified in the MySQL .NET Connector documentation here , it can can provide significant performance improvements on queries that are executed more than once. 正如此处的MySQL .NET Connector文档中所指定的,它可以对多次执行的查询提供显着的性能改进。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM