Вызов хранимой процедуры ASP.NET вставить VarBinary в SQL - PullRequest
0 голосов
/ 04 мая 2018

У меня есть строка байтов данных base64EncodedString из iOS, которая является очень длинной строкой

let imageStr = imageData.base64EncodedString()

Я вызываю .NET-метод из моего ios, который вызывает хранимую процедуру для вставки этих байтов в базу данных.

Вот мой метод .NET, у меня установлен тип данных VarBinary

public string PostLandGradingImages(List<Images> landingCells)
{
    try
    {
        using (connection = new SqlConnection(connectionString))
        {
            connection.Open();

            using (SqlCommand command = new SqlCommand("PostLandGradingImages", connection))
            {
                command.CommandType = CommandType.StoredProcedure;

                for (int i = 0; i < landingCells.Count; i++)
                {
                    command.Parameters.Clear();

                    SqlParameter parameter1 = new SqlParameter("@Job_No", SqlDbType.VarChar);
                    parameter1.Value = landingCells[i].jobNo;
                    parameter1.Direction = ParameterDirection.Input;
                    command.Parameters.Add(parameter1);

                    SqlParameter parameter2 = new SqlParameter("@Image", SqlDbType.VarBinary);
                    parameter2.Value = landingCells[i].imageBytes;
                    parameter2.Direction = ParameterDirection.Input;
                    command.Parameters.Add(parameter2);

                    command.ExecuteNonQuery();
                }
            }
        }
    }
    catch (Exception e)
    {
        return e.Message.ToString();
    }

    return "All Good";
}

Вот мой класс изображений, обратите внимание, что мои imageBytes определены как байты []:

public class Images
{
    public string jobNo { get; set; }
    public byte[] imageBytes { get; set; }
}

Столбец, в который я вставляю, определяется как varbinary (MAX)

и вот моя хранимая процедура:

ALTER PROCEDURE [dbo].[PostLandGradingImages] 
    -- Add the parameters for the stored procedure here
    @Job_No varchar(MAX) = NULL,
    @Image varbinary(MAX) = NULL
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for procedure here
    INSERT INTO LandGradingImages (Job_No, ImageBytes) VALUES (@Job_No, @Image)
END

Моя проблема - ничего не вставляется, я получаю эту ошибку в моем улове:

Ссылка на объект не установлена ​​для экземпляра объекта.

Мой вопрос: что я делаю не так? Я не должен отправлять base64EncodedString или я не правильно устанавливаю свой класс? или моя колонка БД?

Я пробовал это:

byte[] bytes = System.Convert.FromBase64String(landingCells[i].imageBytes);

SqlParameter parameter2 = new SqlParameter("@Image", SqlDbType.VarBinary, 800000);
parameter2.Value = bytes;
parameter2.Direction = ParameterDirection.Input;
command.Parameters.Add(parameter2);

Всё равно не работает :( и я изменил imageBytes на string.

Ответы [ 2 ]

0 голосов
/ 08 мая 2018

Я немного изменил ваш код в соответствии с методом ниже. Он создает новый CommandType.StoredProcedure для каждого Image. Кроме того, результаты возвращаются для каждого изображения, чтобы вы могли увидеть, какие из них не удалось. В вашем методе, если у вас есть 10 изображений, а 9-е не получилось, вы бы этого не знали.

public List<Images> PostLandGradingImages(List<Images> landingCells)
{
    //create a connection to the database
    using (SqlConnection connection = new SqlConnection(Common.connectionString))
    {
        //loop all the images
        for (int i = 0; i < landingCells.Count; i++)
        {
            //create a fresh sql command for every Image
            using (SqlCommand command = new SqlCommand("PostLandGradingImages", connection))
            {
                command.CommandType = CommandType.StoredProcedure;

                //add the parameters
                command.Parameters.Add("@Job_No", SqlDbType.VarChar).Value = landingCells[i].jobNo;
                command.Parameters.Add("@Image", SqlDbType.VarBinary).Value = landingCells[i].imageBytes;

                try
                {
                    //open the connection if closed
                    if (connection.State == ConnectionState.Closed)
                    {
                        connection.Open();
                    }

                    //execute the stored procedure
                    command.ExecuteNonQuery();

                    //set the save result to the image
                    landingCells[i].saveResult = true;
                }
                catch (Exception ex)
                {
                    //handle error per Image
                    landingCells[i].errorMessage = ex.Message;
                }
            }
        }
    }

    return landingCells;
}

Чтобы отследить результат сохранения для изображения, я добавил два свойства в класс Image, но это можно сделать и другими различными способами.

public class Images
{
    public string jobNo { get; set; }
    public byte[] imageBytes { get; set; }

    public bool saveResult { get; set; }
    public string errorMessage { get; set; }
}

Простой тест был выполнен с помощью следующего кода. Никто из них не выдал ошибку NullReference. Даже с обоими свойствами, равными null, запись в базе данных все равно была сделана.

//create a new list with Images
List<Images> landingCells = new List<Images>();

//add some dummy data
landingCells.Add(new Images() { jobNo = null, imageBytes = null });
landingCells.Add(new Images() { jobNo = "Job 1", imageBytes = null });
landingCells.Add(new Images() { jobNo = null, imageBytes = new byte[10000] });
landingCells.Add(new Images() { jobNo = "Job 2", imageBytes = new byte[10000] });

//send the images to be saved
landingCells = PostLandGradingImages(landingCells);

//loop all the images to check the result
for (int i = 0; i < landingCells.Count; i++)
{
    if (landingCells[i].saveResult == false)
    {
        //display the result for each failed image
        Label1.Text += landingCells[i].errorMessage + "<br>";
    }
}

Если по-прежнему существует ошибка NullReference, это означает, что ваш список landingCells сам по себе равен нулю, или объект изображения в этом списке равен нулю (в этом случае он никогда не должен был добавляться в список в первую очередь imho). ). Вы можете легко изменить фрагмент, чтобы проверить это.

0 голосов
/ 07 мая 2018

Рассмотрим пакетирование запросов в транзакции. Также вам следует проверить значения, предоставленные методу, чтобы убедиться, что вы можете правильно вызвать хранимую процедуру.

public int PostLandGradingImages(List<Images> landingCells) {
    int count = 0;
    using (var connection = new SqlConnection(connectionString)) {
        connection.Open();
        //Transaction to batch the actions.
        using (var transaction = connection.BeginTransaction()) {
            foreach (var image in landingCells) {
                if (valid(image)) {//validate input properties.
                    try {
                        using (SqlCommand command = connection.CreateCommand()) {
                            command.CommandType = CommandType.StoredProcedure;
                            command.CommandText = "PostLandGradingImages";
                            command.Parameters
                                .Add("@Job_No", SqlDbType.VarChar, image.jobNo.Length)
                                .Value = image.jobNo;
                            command.Parameters
                                .Add("@Image", SqlDbType.VarBinary, image.imageBytes.Length)
                                .Value = image.imageBytes;
                            count += command.ExecuteNonQuery();
                        }
                    } catch {
                        //TODO: Log error
                    }
                }
            }
            if (landingCells.Count == count) {
                transaction.Commit();
            }
        }
    }
    return count;
}

private bool valid(Images image) {
    return image != null && String.IsNullOrWhiteSpace(image.jobNo)
        && image.imageBytes != null && image.imageBytes.Length > 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...