【问题标题】:How do I read out a blob back to byte array from sqlite?如何从 sqlite 将 blob 读回字节数组?
【发布时间】:2015-09-22 00:59:24
【问题描述】:

我有一个 OpenFileDialog,它允许用户选择单个 .png 图像。我将它存储到一个属性中:

public byte[] HeroesDBThumbnailImage ...
...
if(OFD.ShowDialog() == true)
{
    HeroesDBThumbnailImage = File.ReadAllBytes(OFD.FileName);
    HeroesDBThumbnailPath = OFD.SafeFileName;
}

在此处设置值后,我将按如下方式将条目插入数据库:

query = ....blahblah...
query += "'" Convert.ToBase64String(HeroesDBThumbnailImage) + "','" + Convert.ToBase64String(HeroesDBFeaturedThumbnailImage) + "'); ";

看来是向数据库插入数据,所以我很高兴。

然后,我把它读回来:

new Hero(
...
HThumbnailImage: (byte[])Row["ThumbnailImage"]
) ...

在 XAML 中,我有一个图像,用于测试,我绑定到原始字节数组。一旦用户从文件选择器中选择了图像,绑定到该属性的图像源就会显示该图像。

但是,当我将数据读回另一个属性时,绑定到该字节数组的另一个测试图像不显示任何内容。所有绑定都是正确的,我尝试在运行时调试并且正在读回字节数组,但是它似乎返回了与原始大小不同的大小......原始是 899 字节,一旦从 DB 中读回它似乎是大约 940 ish...

顺便说一下,SQLite DB中的字段是BLOB。

谢谢

编辑:按要求提供的额外信息:

好的,所以在我的英雄类中,我有这个:

public static ObservableCollection<Hero> GetAllHeroes()
{
    ObservableCollection<Hero> Heroes = new ObservableCollection<Hero>();

    try
    {
        var db = new SQLiteDatabase();
        DataTable dt = db.GetDataTable("SELECT * FROM Heroes");
        foreach (DataRow Row in dt.Rows)
        {
            Heroes.Add(new Hero(
                HID: Convert.ToInt32(Row["ID"]),
                HName: Row["Name"].ToString(),
                HGold: Convert.ToInt32(Row["Gold"]),
                HPlatinum: Convert.ToInt32(Row["Platinum"]),
                HDBTag: Row["DBTag"].ToString(),
                HReleaseDate: Convert.ToDateTime(Row["ReleaseDate"]),
                HAvailable: Convert.ToBoolean(Row["Available"]),
                HSale: Convert.ToBoolean(Row["Sale"]),
                HFeatured: Convert.ToBoolean(Row["Featured"]),
                HThumbnailImage: (byte[])Row["ThumbnailImage"],
                HFeaturedThumbnailImage: (byte[])Row["FeaturedThumbnailImage"]
                ));
        }
    }
    catch (Exception err)
    {
        System.Windows.Forms.MessageBox.Show(err.Message);
    }

    return Heroes;
}

它所涉及的 CTOR 是:

public Hero(int HID, string HName, int HGold, int HPlatinum, string HDBTag, DateTime HReleaseDate, bool HAvailable, bool HSale, bool HFeatured, byte[] HThumbnailImage, byte[] HFeaturedThumbnailImage)
{
    ID = HID;
    Name = HName;
    Gold = HGold;
    Platinum = HPlatinum;
    DBTag = HDBTag;
    ReleaseDate = HReleaseDate;
    Available = HAvailable;
    Sale = HSale;
    Featured = HFeatured;
    ThumbnailImage = HThumbnailImage;
    FeaturedThumbnailImage = HFeaturedThumbnailImage;
}

我的视图模型中有以下属性和功能:

private ObservableCollection<Hero> heroesDBHeroes;
public ObservableCollection<Hero> HeroesDBHeroes
{
    get
    {
        return heroesDBHeroes;
    }
    set
    {
        heroesDBHeroes = value;
        OnPropertyChanged("HeroesDBHeroes");
    }
}
private void HeroesDBAddHeroes()
{
    if(HeroesDBHeroes != null)
    {
        HeroesDBHeroes.Clear();
    }
    HeroesDBHeroes = Hero.GetAllHeroes();
}

在需要之前调用 HeroesDBAddHeroes。

然后我有一个绑定到这个 ObservableCollection 的 Datagrid。数据网格表示:

<DataGrid extra:UIElementAttached.IsBubblingMouseWheelEvents="True" ItemsSource="{Binding HeroesDBHeroes}" IsTabStop="False" KeyboardNavigation.TabNavigation="None" Grid.Row="1" IsReadOnly="True">
    <DataGrid.Columns>
        <extra:DataGridTemplateColumn extra:DataGridColumnAttached.CanUserHideColumn="True" AutomationProperties.Name="Image" CanUserSort="True">
            <extra:DataGridTemplateColumn.Header>
                <TextBlock Text="Image" HorizontalAlignment="Center" FontWeight="Bold" FontSize="16" Margin="10,0" />
            </extra:DataGridTemplateColumn.Header>

            <extra:DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Name}" />
                        <Image Source="{Binding ThumbnailImage}" />
                    </StackPanel>
                </DataTemplate>
            </extra:DataGridTemplateColumn.CellTemplate>
        </extra:DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

绑定到 Name 的文本块显示正确,但是绑定到 ThumbnailImage 的图像(也是 Hero 中的 byte[])没有显示任何内容。

【问题讨论】:

  • 这是什么意思-“当我将数据读回另一个属性时,另一个测试图像,绑定到该字节数组不显示任何内容”
  • 这意味着我有一个属性,我使用 HThumbnailImage 设置的属性中显示的代码读取了 blob。我的 xaml 中有一个 ,其中源绑定到此属性。它从不显示图像,即使数据来自数据库。
  • 所以你使用 byte[] 作为图像。资源???这行不通,因为您需要从中提取图像。这是您想要的吗?
  • 它应该可以工作,因为我有另一个 绑定到一个 byte[] 属性,它是在我选择图像时设置的 OpenFileDialog
  • 您使用任何转换器吗?另外,将 xaml 添加到问题中。

标签: c# wpf image sqlite bytearray


【解决方案1】:

在存储数据之前,您使用Convert.ToBase64String()对其进行编码,但是在读取数据时您似乎错过了解码部分Convert.FromBase64String(),即:

byte[] base64Data = (byte[])Row["ThumbnailImage"];
string base64String = System.Text.Encoding.ASCII.GetString(base64Data);
byte[] imageData = Convert.FromBase64String(base64String);

PS。您可能在存储和读取时都跳过 base64 编码,直接存储实际的二进制数据。

【讨论】:

  • 我现在试试,谢谢。关于您对跳过编码的评论...当我构建 SQL 查询并将字节数组附加到字符串时,它显示为类似于“blah ...,System.Byte [],blah ...”这就是我转换它的原因。我是不是做错了什么?
  • 转换效果很好 - 谢谢!仍然会对我如何在没有转换的情况下执行此操作感兴趣:)
  • @MatthewParker 然后您应该使用参数化查询(使用带有SQLiteParameters 的SQLiteCommand)并直接将byte[] 数据分配为其值。
猜你喜欢
  • 2015-01-10
  • 2012-06-06
  • 1970-01-01
  • 2013-02-08
  • 1970-01-01
  • 2018-08-17
  • 1970-01-01
  • 2012-01-30
  • 1970-01-01
相关资源
最近更新 更多