简体   繁体   中英

How do I read out a blob back to byte array from sqlite?

I have an OpenFileDialog which allows users to select a single .png image. I store this into a property as such:

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

Once the value is set there, I am Inserting the entry to the DB as follows:

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

It appears to insert data to the DB, so I was happy.

Then, I read it back as so:

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

in the XAML, I have an image, for testing, which I bound to the original byte array. As soona s the user selects an image from the file selector, the image source, bound to that property, displays that image.

However, when I read the data back into the other property, another test image, bound to that byte array does not display anything. All bindings are correct, and I tried to debug at runtime and the byte array is being read back out, however it appears to be coming back a different size from the original... Original was 899 bytes, once read back out from DB it appears to be about 940 ish...

The field in SQLite DB is BLOB by the way.

Thanks

EDIT: Extra Info provided as requested:

OK, so within my Hero Class, I have this:

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;
}

and the CTOR it relates to is:

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;
}

I have the following Property and function in my viewmodel:

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 is called before it is ever needed.

I then have a Datagrid, bound to this ObservableCollection. Datagrid represented:

<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>

The textblock bound to Name is showing correctly, however the image bound to ThumbnailImage (which is a byte[] also within Hero) is not showing anything.

Before storing the data, you encode it using Convert.ToBase64String() , but when reading the data you seem to miss the decoding part, Convert.FromBase64String() , ie:

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

PS. You could probably skip the base64 encoding on both storing and reading, and store the actual binary data directly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM