在 WPF 中 ImageBox.Source == null 时无法保存 SQLİte

Posted

技术标签:

【中文标题】在 WPF 中 ImageBox.Source == null 时无法保存 SQLİte【英文标题】:Can't Save SQLİte while ImageBox.Source == null in WPF 【发布时间】:2021-12-14 19:30:22 【问题描述】:

我正在尝试将我的数据保存到 sqlite,我的数据也有照片。 我想保存有照片或没有照片的数据。 当我添加照片时,我可以将它保存到 sqlite。但是当 imagebox.Source 为空时,它会给出错误:

'由于对象的当前状态,操作无效。'

它显示错误:

public byte[] BitmapSourceToByteArray(BitmapSource image)

    using (var stream = new MemoryStream())
    
        var encoder = new PngBitmapEncoder(); // or some other encoder
        encoder.Frames.Add(BitmapFrame.Create(image));
        encoder.Save(stream);
        return stream.ToArray();
    

这是我的代码:

    private void SaveButton_OnClick(object sender, RoutedEventArgs e)
    
            BitmapImage image = new BitmapImage();

            if (ImageBox.Source != null)
            
                image.BeginInit();
                image.UriSource = new Uri(filephoto.FileName);
                image.EndInit();
                ImageBox.Source = image;
            

            helper.DataSave("CompanyData", CInfo, image);
       

在助手类中,DataSave;

    public bool DataSave(string TableName, CustomerInfo CInfox, BitmapImage obj) // Save to DataBase
    
        //try
        //
            ConOpen();
            string query = $"Insert Into TableName (Company, Product, Product_No, Product_Size, Photo) Values (@company, @product, @pno, @psize, @photo)";
            SQLiteCommand komut = new SQLiteCommand(query, connection);

            SQLiteParameter param1 = new SQLiteParameter("@company", DbType.String);
            SQLiteParameter param2 = new SQLiteParameter("@product", DbType.String);
            SQLiteParameter param3 = new SQLiteParameter("@pno",     DbType.String);
            SQLiteParameter param4 = new SQLiteParameter("@psize",   DbType.String);
            SQLiteParameter param5 = new SQLiteParameter("@photo",   DbType.Binary);

            param1.Value = CInfox.Customer;
            param2.Value = CInfox.Product;
            param3.Value = CInfox.ProductNo;
            param4.Value = CInfox.ProductSize;
            param5.Value = BitmapSourceToByteArray(obj);


            komut.Parameters.Add(param1);
            komut.Parameters.Add(param2);
            komut.Parameters.Add(param3);
            komut.Parameters.Add(param4);
            komut.Parameters.Add(param5);

            komut.ExecuteNonQuery();
            MessageBox.Show("Saved Succesfully!");
            ConClose();
            return true;
    

【问题讨论】:

确保你在配置文件<configuration> <appSettings> <add key="aspnet:MaxJsonDeserializerMembers" value="1000" /> </appSettings> </configuration>中有这个设置 数据库中保存图像数据的列是否允许空值?如果是这样,您可能需要以某种方式处理空值。此外,您可能希望将整个数据库事务包装在 Try/Catch/Finally 块中,以确保数据库连接始终关闭。 @joshman1019 但它是允许的。我一直在尝试,但结果是一样的。 【参考方案1】:

由于您的数据库将接受空值,您可能需要重构:

    public bool DataSave(string TableName, CustomerInfo CInfox, BitmapImage obj) // Save to DataBase

    try
    
        ConOpen();
        string query = $"Insert Into TableName (Company, Product, Product_No, Product_Size) Values (@company, @product, @pno, @psize)";
        SQLiteCommand komut = new SQLiteCommand(query, connection);

        SQLiteParameter param1 = new SQLiteParameter("@company", DbType.String);
        SQLiteParameter param2 = new SQLiteParameter("@product", DbType.String);
        SQLiteParameter param3 = new SQLiteParameter("@pno",     DbType.String);
        SQLiteParameter param4 = new SQLiteParameter("@psize",   DbType.String);

        param1.Value = CInfox.Customer;
        param2.Value = CInfox.Product;
        param3.Value = CInfox.ProductNo;
        param4.Value = CInfox.ProductSize;

        komut.Parameters.Add(param1);
        komut.Parameters.Add(param2);
        komut.Parameters.Add(param3);
        komut.Parameters.Add(param4);

        if(obj is not null) // if(obj != null) for older C# versions
        
            string query = $"Insert Into TableName (Company, Product, Product_No, Product_Size, Photo) Values (@company, @product, @pno, @psize, @photo)";
            SQLiteParameter param5 = new SQLiteParameter("@photo",   DbType.Binary);
            param5.Value = BitmapSourceToByteArray(obj);
            komut.Parameters.Add(param5);
        

        komut.ExecuteNonQuery();
        MessageBox.Show("Saved Succesfully!");

   
   catch(Exception)
   
        // Handle exceptions here or let it bubble up to caller (You should use transactions)
   
   finally
   
        ConClose();
   
        return true;

附加信息。图像转换助手

    internal static class SignatureImageConversion

    public static BitmapImage ConvertFileToBitmap(this string path)
    
        BitmapImage image = new BitmapImage();
        image.BeginInit();
        image.UriSource = new Uri(path);
        image.EndInit();
        return image; 
    

    public static BitmapImage ConvertFileStreamToBitmap(this byte[] stream)
    
        BitmapImage image = new BitmapImage();
        image.BeginInit();
        image.StreamSource = new MemoryStream(stream);
        image.EndInit();
        return image; 
    

    public static byte[] ConvertImageToByteArray(this BitmapImage image)
    
        byte[] data = null; 
        JpegBitmapEncoder jpencoder = new JpegBitmapEncoder();
        jpencoder.Frames.Add(BitmapFrame.Create(image));
        using (MemoryStream ms = new MemoryStream())
        
            jpencoder.Save(ms);
            data = ms.ToArray();
        
        return data;
    

【讨论】:

我做了这段代码,但是当我点击保存按钮时,没有任何反应。没有错误,没有数据库信息,什么都没有。 如果您正在调用某个对话框或另一个基于 UI 的消息源,它可能不会显示,因为这些事件不在 UI 线程上。 好吧,我做到了,但同样的错误再次出现。 当你在断点处检查代码时,obj实际上是否为null,或者obj中是否设置了其他值? 我回复了我的帖子,有一种情况。它适用于代码。但它不适用于另一个代码。你能检查一下吗【参考方案2】:

默认情况下最大大小为1000,如果您发布要反序列化的大数据,则需要增加它。

<appSettings>
  <add key="aspnet:MaxJsonDeserializerMembers" value="2000" />
</appSettings>

将此属性设置为太大的数字可能会带来安全风险。

【讨论】:

【参考方案3】:
<appSettings>
  <add key="aspnet:MaxJsonDeserializerMembers" value="2000" />
</appSettings>

这适用于我的其他代码。但它仍然不适用于我上面共享的代码。

它适用于:

    private void SaveButton_OnClick(object sender, RoutedEventArgs e)
       BitmapImage image = null;
        if (ImageBox.Source != null)
        
            image = new BitmapImage();
            image.BeginInit();
            image.UriSource = new Uri(filephoto.FileName);
            image.EndInit();
            ImageBox.Source = image;
        
        helper.DataSave("CompanyData", CInfo, image);
        

它不起作用:

        BitmapImage image = new BitmapImage();

        if (ImageBox.Source != null)
        
            image.BeginInit();
            image.UriSource = new Uri(filephoto.FileName);
            image.EndInit();
            ImageBox.Source = image;
        

        helper.DataSave("CompanyData", CInfo, image);

【讨论】:

您在 cmets 中说它对您有用,然后您删除了您的评论并添加了我的答案作为您的答案。这不公平。 我认为他在进行图像转换时还有其他一些问题。我认为此时不存在序列化问题。不过,您的答案在底部。 @viveknuna,我是这个网站的新手,所以我的目的是回答你的评论,我不知道这一点。所以告诉我做对了。 @Serhatözyıldız 如果有人帮助您或花一些时间帮助您,这是出于礼貌 @viveknuna 我知道。所以我对发生的事情感到抱歉。正如我所说,我只是想为您的答案添加评论。如果有什么办法可以解决,直接说吧。我也可以删除我的答案。

以上是关于在 WPF 中 ImageBox.Source == null 时无法保存 SQLİte的主要内容,如果未能解决你的问题,请参考以下文章

wpf窗体添加事件的地方在哪里?

WPF 窗口中展现网页

WPF 在WPF中使用SVG文件作为图标的正确方法是啥

在wpf中怎么绑定comboBox的值

WinForm中调用WPF控件

wpf开发中 xaml 添加名称空间