У меня возникают проблемы с POST и PUT для моего бэкэнда. Соответствующую структуру таблицы можно увидеть здесь
DROP TABLE IF EXISTS coordinate;
CREATE TABLE coordinate
(
id int(10) NOT NULL auto_increment,
longitude double(8,4) NOT NULL,
latitude double(8,4) NOT NULL,
measurementId int(10) default NULL,
PRIMARY KEY (id),
FOREIGN KEY (measurementId)
REFERENCES measurement (id)
ON DELETE CASCADE
);
У него есть соответствующий Model, который выглядит так
public class Coordinate
{
public Coordinate()
{
}
public int ID { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public int MeasurementId { get; set; }
...
}
Я пытаюсь вставить числовые значения в coordinate вот так:
sql = "UPDATE coordinate SET longitude = '" + coordinate.Longitude + "," + " latitude = " + coordinate.Latitude + "," + " measurementId = " + coordinate.MeasurementId + "' WHERE id = " + id.ToString();
Обратите внимание на включение одинарной скобки перед двойной скобкой после longitude = '" и + "' WHERE ....
Когда я запускаю это с помощью отладчика, строка sql создается следующим образом:
sql = "UPDATE coordinate SET longitude = '55,6, latitude = 70,33, measurementId = 2' WHERE id = 2'
И мой бэкэнд выдает следующую ошибку:
{
"Message": "An error has occurred.",
"ExceptionMessage": "Data truncated for column 'longitude' at row 1",
"ExceptionType": "MySql.Data.MySqlClient.MySqlException",
...
}
Я предполагаю, что строка sql построена неправильно из-за включения одинарной скобки, поэтому я удаляю ее и создаю новую строку sql следующим образом:
sql = "UPDATE coordinate SET longitude = " + coordinate.Longitude + "," + " latitude = " + coordinate.Latitude + "," + " measurementId = " + coordinate.MeasurementId + " WHERE id = " + id.ToString();
Обратите внимание на удаление одиночной скобки ' в тех местах, где она была раньше. Теперь в отладчике строка sql строится так:
sql = "UPDATE coordinate SET longitude 55,6 latitude = 70,33, measurementId = 2 WHERE id = 2"
У меня сложилось впечатление, что числовые значения должны быть разделены ., а не ,, что может быть причиной того, что серверная часть теперь выдает эту ошибку:
{
"Message": "An error has occurred.",
"ExceptionMessage": "You have an error in your SQL syntax; check the manual
that corresponds to your MySQL server version for the right syntax to use
near '6, latitude = 70,33, measurementId = 2 WHERE id = 2' at line 1",
}
Я немного не понимаю, как обрабатывать вставку числовых значений в мою базу данных. Любая помощь горячо приветствуется.
Используйте параметры. У вас не будет проблем с синтаксисом
@АлексК. Хорошо, рассмотрим это.
INSERT. Однако параметризованные запросы мощь решают эту проблему, как и @AlexK. предложено - определенно стоит попробовать, поскольку теоретически параметры устраняют двусмысленность, описанную в связанном ответе (и которую вы видите здесь)





Попробуйте следующее.
sql = "UPDATE coordinate SET longitude = '" + coordinate.Longitude + "', latitude = '" + coordinate.Latitude + "', measurementId = '" + coordinate.MeasurementId + "' WHERE id = " + id.ToString();
@ShyamVemula Нет, данные усекаются (первая ошибка, которую я выделил в своем вопросе)
@ShyamVemula ошибка усечения данных означает, что запрос выполнен, чего он не сделал бы, если бы была синтаксическая ошибка.
каковы datatypes столбцы долготы и широты?.
@ShyamVemula double, как указано в моем вопросе в самом верху.
Эти столбцы имеют тип данных double, а данные, которые вы передаете, — 55,6 и 70,33. ALTER типы данных столбца в char(20)
@ShyamVemula Я знаю, что они double, и нет, я прохожу нет55,6 - это преобразование происходит где-то в цепочке. Данные должны храниться в базе данных как правильное числовое значение, а не как char.
Может быть, попробовать следующее. Я думаю, проблема в том, что вам нужно использовать '.' вместо ',', чтобы сделать десятичные значения понятными для SQL. Имейте в виду, что когда вы пытаетесь вернуть долготу/широту, она будет возвращена в виде строки.
Я не проверял это, но попробуйте.
using System.Globalization;
public class Coordinate
{
NumberFormatInfo nfi = new NumberFormatInfo();
public Coordinate()
{
nfi.NumberDecimalSeparator = ".";
}
public int ID { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public int MeasurementId { get; set; }
public string GetLatitudeComma()
{
return this.Latitude.ToString(nfi);
}
public string GetLongitudeComma()
{
return this.Longitude.ToString(nfi);
}
}
А также...
sql = "UPDATE coordinate SET longitude = '" + coordinate.GetLongitudeComma() + "," + " latitude = " + coordinate.GetLatitudeComma()+ "," + " measurementId = " + coordinate.MeasurementId + "' WHERE id = " + id.ToString();
Возвращает строку из свойств, введенных как double? А также условие переполнения стека.
Хорошо, внес изменения, чтобы он действительно скомпилировался, проблема только в запятых, удалите их, и вы золотой. Вы можете сделать это по-другому с помощью 'coordinate.Latitude.ToString().Replace(',','.')', но это может привести к грязному коду.
@DubDub Немного хакерский, но сработало :-) Спасибо!
заменять «ОБНОВЛЕНИЕ координат SET долгота = '55,6, широта = 70,33, MeasurementId = 2' ГДЕ id = 2' к «ОБНОВЛЕНИЕ координат SET: долгота = ‘55,6’, широта = ‘70,33’, MeasurementId = ‘2’, ГДЕ id = ‘2’
заменить "," на "." (от 55,6 до 55,6) sql не читает и не записывает число с ","
Как указано в комментариях к моему вопросу, использование параметризованного запроса решило проблему с дополнительным преимуществом защиты SQL-запроса. Хотя ответ DubDub был хорошим обходным путем, следующее решает его более масштабируемым и безопасным способом.
SQL-запрос теперь выглядит так:
string sql = "UPDATE coordinate SET longitude = @Longitude, latitude = @Latitude, measurementId = @MeasurementId WHERE id = @ID";
List<MySqlParameter> parameters = SqlFactory.CreateParametersFor(coordinate);
cmd = SqlFactory.CreateParameterizedQuery(sql, parameters, conn);
cmd.Parameters.Add(ID);
await cmd.ExecuteNonQueryAsync();
Где CreateParametersFor() и CreateParameterizedQuery() реализованы так:
public static MySqlCommand CreateParameterizedQuery(string sql, List<MySqlParameter> parameters, MySqlConnection connection)
{
MySqlCommand cmd = new MySqlCommand(sql, connection);
foreach (MySqlParameter parameter in parameters) cmd.Parameters.Add(parameter);
return cmd;
}
public static List<MySqlParameter> CreateParametersFor(Coordinate coordinate)
{
List<MySqlParameter> parameters = new List<MySqlParameter>();
MySqlParameter latitude = new MySqlParameter()
{
ParameterName = "@Latitude",
Value = coordinate.Latitude
};
MySqlParameter longitude = new MySqlParameter()
{
ParameterName = "@Longitude",
Value = coordinate.Longitude
};
MySqlParameter measurementId = new MySqlParameter()
{
ParameterName = "@MeasurementId",
Value = coordinate.MeasurementId
};
parameters.Add(latitude);
parameters.Add(longitude);
parameters.Add(measurementId);
return parameters;
}
Бум, это выглядит намного лучше в конце. Я рекомендую изменить заголовок вопроса, чтобы включить где-то «десятичные значения, разделенные запятыми», потому что это было проблемой. Кроме того, если вы заинтересованы в эффективности/безопасности/масштабируемости кода, возможно, проведите некоторое исследование хранимых процедур, чтобы вы могли отделить свой бизнес-уровень от уровня доступа к данным. (например, обычно не идеально иметь sql в бэкэнде страниц, он должен быть в своих собственных классах или иным образом)
@DubDub Я посмотрю на это. Я обновил название вопроса, чтобы отразить фактическую проблему. Спасибо за вашу помощь :-)
Вам нужно переписать это как параметризованный запрос, чтобы исправить имеющуюся у вас уязвимость SQL Injection, тогда вам не понадобится конкатенация строк, чтобы избежать несбалансированных кавычек, отсутствующих символов и т. д. Это также устранит несколько проблем с форматированием.