В настоящее время я разрабатываю студенческий портал с подходящей и простой системой входа в систему для проекта последнего года обучения в моем колледже. Это одна из командных кнопок (для сохранения фотографии на SQL-сервере). Я обнаружил ошибку. Это сообщение об ошибке:
System.Data.SqlClient.SqlException: 'String or binary data would be truncated. The statement has been terminated.'
Private Sub Button8_Click(sender As Object, e As EventArgs) Handles Button8.Click
'String imagelocation = ""
Dim images() As Byte = Nothing
'Dim imagelocation As String
'imagelocation = ""
Dim Stream As New FileStream(imagelocation, FileMode.Open, FileAccess.Read)
Dim brs As New BinaryReader(Stream)
images = brs.ReadBytes(CInt(Stream.Length))
Dim source As String = "Data Source=LAPTOP-85ALBAVS\SQLEXPRESS;Initial Catalog=Portal;Integrated Security=True"
Dim con As New SqlConnection(source)
con.Open()
Dim cmd As String = "Insert into Photo Values('" + TextBox2.Text + "', @images)"
Dim qry As New SqlCommand(cmd, con)
qry.Parameters.Add(New SqlParameter("@images", images))
'qry.Parameters.Add(new SqlParameter("@images", pictureBox1));
***Dim i As Integer = qry.ExecuteNonQuery()
If i >= 1 Then
MessageBox.Show("Successfull!", "message", MessageBoxButtons.OK)
Else
MessageBox.Show("Fail!", "message", MessageBoxButtons.OK)
End If
End Sub
End Class
Это таблица SQL для меня, чтобы сохранить загруженную фотографию в базу данных. Любая помощь будет оценена по достоинству. Спасибо.
ОБНОВИТЬ
Ранее имя столбца Photo
было изменено на Img
, имя таблицы должно было быть Photo
.
Поэтому я попытался переключить код на другой метод:
Dim source As String = "Data Source=LAPTOP-85ALBAVS\SQLEXPRESS;Initial Catalog=Portal;Integrated Security=True"
Dim con As New SqlConnection(source)
Dim command As New SqlCommand("Insert into Photo (Img, Pname) Values (@Img, @Pname)", con)
Dim ms As New MemoryStream
pictureBox1.Image.Save(ms, pictureBox1.Image.RawFormat)
command.Parameters.Add("@Img", SqlDbType.Image).Value = ms.ToArray()
command.Parameters.Add("@Pname", SqlDbType.VarChar).Value = TextBox2.Text
con.Open()
If command.ExecuteNonQuery() = 1 Then
MessageBox.Show("Successfully uploaded", "Message", MessageBoxButtons.OK)
Else
MessageBox.Show("Failed. Try again.", "Message", MessageBoxButtons.OK)
End If
Думаю, это действительно сработало. Не уверен, будет ли какая-нибудь скрытая ошибка. Любой комментарий был бы полезен, ребята. Это результат таблицы Photo
.
Photo
таблица вывода
Как сказал @jmcilhinney, вам нужно отладить свой код и пройти через него, чтобы определить, какой оператор вызывает исключение, и просто опубликовать код, относящийся к этому оператору. Кроме того, я бы рекомендовал почитать параметризованные операторы SQL, поскольку в настоящее время ваш код широко открыт для атак с использованием SQL-инъекций.
Можете ли вы указать тип данных для каждого столбца в таблице Photo
? Также вы, кажется, используете конкатенацию для строки запроса, вместо этого используйте параметры.
@TetsuyaYamamoto. Да, ссылка на изображение с названием «Таблица» является типом данных для таблицы Photo
. Поскольку я никогда не узнал о параметрах, поэтому я его не использую.
Вам не потребовались бы легенды для элементов управления, если бы вы дали им значащие имена. Пожалейте беднягу, которому приходится поддерживать ваш код.
@ Мэри, прости за беспокойство. Поскольку я разрабатываю его, я полагаю, что использовать имена по умолчанию для кнопок мне проще. Я упомянул легенду только для справки, так как по ошибке загрузил весь абзац кода, что не рекомендуется. Я не буду повторять эту ошибку снова. Спасибо :)
Это второй раз за столько дней, когда появилась эта перегрузка конструктора для параметров. qry.Parameters.Add(New SqlParameter("@images", images))
Это эквивалент .AddWithValue, вызвавшего исключение. (см. ответ @Tetsuya Yamamoto) Используйте перегрузку метода .Add, для которой требуется тип и размер данных.
Эта ошибка возникает, когда вы указываете размер параметра, а затем предоставляете данные, превышающие его. Для начала, способ добавления параметра плохой:
qry.Parameters.Add(New SqlParameter("@images", images))
Вы не указываете там тип данных или размер, поэтому полагаетесь на то, что системный тип по умолчанию в порядке. Очевидно, что это не так, иначе вы не получили бы эту ошибку. ВСЕГДА указывайте тип данных и, если тип данных - переменный размер, также и размер, например
qry.Parameters.Add("@images", SqlDbType.VarBinary, 8000).Value = images
Указанное вами значение SqlDbType
должно соответствовать типу данных столбца, для которого предназначены данные, а размер также должен соответствовать размеру в базе данных. Если вы используете varbinary(max)
в базе данных, используйте -1 для размера параметра.
На самом деле проблема только с кодами для button8
, остальное нормально. Я отправляю весь параграф кодов на всякий случай просто для справки. Фотография предназначена для загрузки в таблицу Photo
. Как показано на прилагаемом снимке экрана, Table
- это тип данных, который я использую для таблицы Photo
.
«в остальном все в порядке. Я отправляю весь параграф кодов на всякий случай только для справки». Не надо. Если нам нужно больше, мы можем попросить об этом, но вы должны публиковать только тот код, который имеет непосредственное отношение к проблеме.
В документации четко указано, что тип данных image
устарел, поэтому у вас нет веских причин использовать его в новой базе данных. Вы должны использовать varbinary
. В любом случае, если вы используете image
, вам все равно следует указывать это в качестве типа данных для параметра. Поскольку вы используете массив Byte
, он почти наверняка будет использовать по умолчанию SqlDbType.VarBinary
, а также использовать некоторый размер по умолчанию (вероятно, 4000 или 8000), и ваши данные должны превышать этот размер. Если вы сделаете то, что я уже сказал вам, и определитесь с типом и размером данных, тогда это сработает.
Во-первых, вы должны знать, что использование типа данных IMAGE
не рекомендуется. Более рекомендуется использование VARBINARY(MAX)
:
ALTER TABLE TableName ALTER COLUMN Photo VARBINARY(MAX)
Объяснение об устаревании типа данных изображения можно увидеть здесь.
For storing images you have to make use of the varbinary(MAX) datatype. The image datatype will be deprecated.
Затем исключение произошло из-за того, что вы добавляете данные в столбец изображения, размер которого меньше, чем размер переданного изображения из параметра (поскольку SqlDbType
не указан, CLR автоматически определяет тип Byte(n)
; следовательно, может произойти усечение данных, чтобы соответствовать переданному массиву для типа данных IMAGE
) . Используйте SqlDbType.VarBinary
с размером -1
:
qry.Parameters.Add("@images", SqlDbType.VarBinary, -1).Value = images
Обратите внимание, что вы можете установить максимальный размер VARBINARY
с определенными числами в байтах (кроме -1
), но вам нужно проверить images.Length
, чтобы предотвратить усечение (просто отмените процесс загрузки, если размер изображения больше указанного).
If images.Length > 1048576 Then ' maximum limit e.g. 1 MiB
' cancel upload
Else
' continue and save to DB
End If
Наконец, настройте запрос, чтобы использовать параметры для всех значений:
Dim source As String = "Data Source=LAPTOP-85ALBAVS\SQLEXPRESS;Initial Catalog=Portal;Integrated Security=True"
Using con As New SqlConnection(source)
con.Open()
Dim cmd As String = "Insert into Photo Values(@pname, @images)"
Using qry As New SqlCommand(cmd, con)
qry.Parameters.Add("@pname", SqlDbType.NVarchar, 50).Value = TextBox2.Text
qry.Parameters.Add("@images", SqlDbType.VarBinary, -1).Value = images
Dim i As Integer = qry.ExecuteNonQuery()
' other stuff
End Using
End Using
Хорошо, поэтому я скорректировал конкретный запрос, который вы упомянули, и, используя тип данных varbinary
для images
, установил размер на -1
. Однако есть ошибка System.Data.SqlClient.SqlException: 'Implicit conversion from data type nvarchar to varbinary(max) is not allowed. Use the CONVERT function to run this query.'
с этим запросом: Dim i As Integer = qry.ExecuteNonQuery()
@Tetsuya Yamamoto Из предоставленной вами ссылки «Varbinary (max) может хранить только изображения с максимальным размером 2 ГБ». Но в вашем комментарии говорится: «Максимальный предел, например, 1 МБ». Это какие-то другие критерии, которые дополнительно ограничивают ограничение в 2 ГБ?
Это слишком много кода для публикации. Вам нужно потратить некоторое время на решение проблемы самостоятельно и несколько сузить ее, а затем опубликовать ТОЛЬКО соответствующий код.