我有一个字符串,它是来自iOS的数据字节base64EncodedString,这是一个非常长的字符串
let imageStr = imageData.base64EncodedString()
我从我的ios调用.NET方法,它将调用存储过程将这些字节插入数据库。
这是我的.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";
}
这是我的Image Class,请注意我的imageBytes被定义为byte []:
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或者我没有设置我的课程吗?还是我的db列?
我试过了:
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更改为字符串。
答案 0 :(得分:3)
我将您的代码稍微修改为以下方法。它会为每个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错误,则表示您的List landingCells
本身为null,或者该List中的Image对象为null(在这种情况下,它应该永远不会被添加到List中)放置imho)。您可以轻松更改代码段以进行检查。
答案 1 :(得分:0)
考虑在事务中批处理查询。此外,您应验证提供给方法的值,以确保您可以正确调用存储过程。
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;
}