Я работаю над игрой уже около 2 месяцев и использую базу данных SQL Server для хранения всех данных об игроке. Я пытался записать данные в таблицу Players, но пока безуспешно.
Я попробовал создать метод, в котором я устанавливаю соединение с базой данных и вставляю данные через SqlCommand
(SqlClient
).
DataManager
класс
public static void UpdatePlayerStatistics(string connectionString, string[] playerTextData, int[] playerIntData)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand($"INSERT INTO dbo.Players VALUES ({playerTextData[0]})", connection);
cmd.CommandType = System.Data.CommandType.Text;
cmd.Parameters.AddWithValue("@PlayerName", playerTextData[0].ToString());
connection.Open();
cmd.ExecuteNonQuery();
connection.Close();
}
}
Game
класс:
public static string[] playerTextData = new string[4];
/*
* 0 - PlayerFirstName
* 1 - PlayerLastName
* 2 - PlayerRace
* 3 - PlayerClass
*/
public static void Main(string[] args)
{
// Receives player's first name
Console.WriteLine("Please enter your character's first name: ");
playerTextData[0] = Console.ReadLine();
Console.Clear();
// Receives player's last name
Console.WriteLine("Please enter your character's last name: ");
playerTextData[1] = Console.ReadLine();
Console.Clear();
// Uploads the basic data to table
DataManager.UpdatePlayerStatistics(playerTextData, playerIntData);
}
И еще при тестировании вылезла такая ошибка
System.Data.SqlClient.SqlException: неверное имя столбца
<First Name>
. Неверное имя столбца<Last Name>
. Имя столбца или количество предоставленных значений не соответствует определению таблицы.
Вы не определяете, в какие столбцы вы вставляете. Какие столбцы существуют в таблице «Игроки»? Кроме того, вам может быть сложнее использовать массив для хранения имени и фамилии игрока. Возможно, это будет проще понять, если вы используете разные именованные переменные и/или класс. Совершенно произвольно говорить: «В этом массиве индекс 0 является именем, а индекс 1 — фамилией».
Пометить это ssms — это все равно, что сообщить нам, что машина, на которой вы ездите, — Sony, потому что эта марка указана на приборной панели магнитолы.
Кроме того, НЕ НУЖНО использовать интерполяцию или конкатенацию строк для включения данных в команду sql. Это одна из тех вещей, которые слишком важны, чтобы делать что-то неправильно, даже для обучения/практики/проверки концептуальной работы.
Наконец, не используйте массивы строк для хранения полей. Определите класс со свойствами для каждого поля. Если вы этого не умеете, значит, вы еще не готовы научиться использовать базы данных.
Это ответ на ваш вопрос? Почему мы всегда предпочитаем использовать параметры в операторах SQL?
Здесь есть чем заняться. Примечания в виде комментариев для пояснения изменений.
// Do NOT use array elements as fields! Classes (or Records) are so much better for this.
public class PlayerData
{
public string FirstName {get;set;}
public string LastName {get;set;}
public string Race {get;set;}
public string Class {get;set;}
}
// Again: if a class is this simple, with only basic auto-implemented properties, it should probably be a record.
// I left it as a class because someone new to C# may not have seen records yet.
// Also remember, you'll be able to re-use this class when going the other direction and selecting data back out of the database.
public class Program
{
public static void Main(string[] args)
{
// create our player object closer to where it's used
var player = new PlayerData();
// Receives player's first name
Console.WriteLine("Please enter your character's first name: ");
player.FirstName = Console.ReadLine();
Console.Clear();
// Receives player's last name
Console.WriteLine("Please enter your character's last name: ");
player.LastName = Console.ReadLine();
Console.Clear();
// Uploads the basic data to table
DataManager.UpdatePlayerStatistics(player);
}
}
public class DataManager
{
// private connection string.
// Now other types won't be able to connect on their own (no string).
// This forces data access to go through your data manager, where it belongs.
// Some apps may opt to have this set via a constructor, load it
// from a config file or similar, or use dependency injection
private static string connectionString = "connection string here";
// No longer need to pass connection string as an argument
// Also, we can accept the PlayerData type, with nice named fields
public static void UpdatePlayerStatistics(PlayerData player)
{
// this could be *const* if we wanted... it will never change!
// However, I had to guess at the column names.
// Also note how I included the parameter variables in the string
string sql = "INSERT INTO dbo.Players (FirstName, LastName) VALUES (@FirstName, @LastName);";
using var connection = new SqlConnection(connectionString);
using var cmd = new SqlCommand(sql, connection);
// Do NOT use AddWithValue() (it has a serious performance "gotcha" that can crop up)
// DO use the exact database column type and size from the database
cmd.Parameters.Add("@FirstName", SqlDbType.NVarChar, 20).Value = player.FirstName;
cmd.Parameters.Add("@LastName", SqlDbType.NVarChar, 25).Value = player.LastName;
connection.Open();
cmd.ExecuteNonQuery();
// No need to call .Close() because the using directive takes care of it in a better way
}
}
@HansKeffing Исправлено, хороший улов.
я думаю, что самый простой способ:
ExampleEntities1 db = new ExampleEntities1();
Tbl(your table name) D = new Tbl(your table name)();
D.PlayerFirstName = TxtPlayerFirstName.Text;
D.PlayerLastName = TxtPlayerLastName.Text;
D.PlayerClass = TxtPlayerClass.Text;
D.PlayerRace = Convert.ToInt32(PlayerRace.Text);
db.Tbl(your table name).Add(D);
db.SaveChanges();
this.DialogResult = DialogResult.OK;
таким образом вы легко можете добавить свою дату в winform в базу данных.
Не используйте конкатенацию строк для построения команды SQL. В лучшем случае это приведет к таким проблемам, а в худшем — к атакам с использованием SQL-инъекций. Всегда параметризуйте свои утверждения. Вы определили параметр
@PlayerName
, но никогда его не используете.