Using a native database with Javascript,C#, VB and C++/CX in Windows 8 modern APP: Part I
Introduction
With the Windows Runtime available in Windows 8, there is no natural easy way to create a local cache, and to query data in this cache (Except SQLLite).
Nevertheless, with Windows is available (for X86,X64, and ARM) the Extensible Storage Engine API. Is an ISAM (Indexed Sequential Access Method) data storage technology, which allows, to create Database, with tables and indexes (Numerous Windows components take advantage of ESE, such as Exchange Server, Active Directory or Desktop Search).
Because the API are only a C API and not really easy to use, I’m working on a C++/CX, which can be use easily from, Javascript, C#/VB and C++.
With this wrapper you can
- Create a Database
- Create tables, with fields and indexes
- Use Transaction
- Adding, Deleting and updating records
- Navigate through cursor sequentially or using indexes
But let’s begin with the basics.
Initializing the engine
First you need to add JetBlue.WinRT as a reference in your project,
Then initialize the engine as shown in the following code snippet
Code VB.NET
Dim m_engine = New JetBlue.WinRT.JetBlueEngine()
m_engine.Error.ThrowException = True
m_engine.BeginSession()
Code C#
var m_engine = new JetBlue.WinRT.JetBlueEngine();
m_engine.Error.ThrowException = true;
m_engine.BeginSession();
Code C++/CX
auto m_engine = ref new JetBlue::WinRT::JetBlueEngine();
m_engine->Error->ThrowException = true;
m_engine->BeginSession();
Code Javascript
var m_engine = new JetBlue.WinRT.JetBlueEngine(true);
m_engine.error.throwException = true;
m_engine.beginSession();
First you need to instantiate the engine, with the JetBlueEngine().
By default the engine raise the OnJetBlueError event, if you want to use a try-catch statement instead , you need to set to true the ThrowException parameter.
With Windows 8, it is not possible for a Custom Exception to go through the ABI. It is the raison why, I use the GetLastErrorMessage() mechanism, in order to get the error message. But this issue is fix with Windows 8.1, so I will be able to use a Custom Exception when porting my component to 8.1.
Exception
- catch (Exception ex)
- {
- var error = m_engine.GetLastErrorMessage();
- }
Because some differences exist between Javascript and the others ModernUI languages, I need to know for internal algorithms ,if a Javascript App is calling me. This is why, I use the JetBlueEngine(true) overloaded constructor in the Javascript sample above.
To stop the engine, use the m_engine.EndSession() method.
Creating the Database
In order to create a database you can use the JetBlueDatabase^ CreateDatabase(Platform::String^ dbname,CreateDatabaseFlags flags), method.
Code VB.NET
Dim db = m_engine.CreateDatabase("TestDB.EDB", JetBlue.WinRT.Enum.CreateDatabaseFlags.OverwriteExisting)
Code C#
var db = m_engine.CreateDatabase("TestDB.EDB", JetBlue.WinRT.Enum.CreateDatabaseFlags.OverwriteExisting);
Code C++/CX
auto db = m_engine->CreateDatabase("TestDB.EDB", JetBlue::WinRT::Enum::CreateDatabaseFlags::OverwriteExisting);
Code Javascript
var db = m_engine.createDatabase("TestDB.EDB", JetBlue.WinRT.Enum.CreateDatabaseFlags.overwriteExisting);
The db variable contain a JetBlueDatabase instance. But if you prefer, you can use the asynchronous method (The main target for the asynchronous method are to avoid freezing the interface)
IAsyncOperation<JetBlueDatabase^>^ CreateDatabaseAsync(Platform::String^ dbname,CreateDatabaseFlags flags)
Code C++/CX
task<JetBlueDatabase^> taskDb(m_engine->CreateDatabaseAsync("TestDB.EDB", CreateDatabaseFlags::OverwriteExisting));
taskDb.then([this,m_engine,group1](JetBlueDatabase^db)
{
Code Javascript
m_engine.createDatabaseAsync("Test.edb", JetBlue.WinRT.Enum.CreateDatabaseFlags.overwriteExisting).then(function (db) {
Use the async/await key word with C# or VB.
Don’t forget to close the database, with db.Close().
Creating a table
To create a table, you have the choice to choose one of the overloaded CreateTable methods.
JetBlueTable^ CreateTable(Platform::String^ tablename, IVector<JetBlueColumn^>^ columns)
or overloaded asynchronous methods
IAsyncOperation<JetBlueTable^>^ CreateTableAsync(Platform::String^ tablename, IVector<JetBlueColumn^>^ columns);
In the code snippet below, the CreateTable method, takes two parameters, the table name, and a collection of JetBlueColumn objects. A collection of JetBlueColumn takes a special place, as a pivot, in order to create a table, but also, to navigate in a cursor and to get value when querying a table.
Code VB.NET
Dim listcolumns = New List(Of JetBlue.WinRT.JetBlueColumn)()
listcolumns.Add(New JetBlue.WinRT.JetBlueColumn("Nom", ColumnType.Text, ColumnFlags.NotNull))
listcolumns.Add(New JetBlue.WinRT.JetBlueColumn("Prnom", ColumnType.Text, ColumnFlags.NotNull))
listcolumns.Add(New JetBlue.WinRT.JetBlueColumn("Age", ColumnType.Int32, ColumnFlags.NotNull))
listcolumns.Add(New JetBlue.WinRT.JetBlueColumn("PicturePath", ColumnType.Text, ColumnFlags.NotNull))
listcolumns.Add(New JetBlue.WinRT.JetBlueColumn("Description", ColumnType.Text, ColumnFlags.NotNull))
listcolumns.Add(New JetBlue.WinRT.JetBlueColumn("itemContent", ColumnType.LongText, ColumnFlags.MaybeNull))
Dim table = db.CreateTable("TETable", listcolumns)
Code C#
var listcolumns = new List<JetBlue.WinRT.JetBlueColumn>();
listcolumns.Add(new JetBlue.WinRT.JetBlueColumn("Nom", ColumnType.Text, ColumnFlags.NotNull));
listcolumns.Add(new JetBlue.WinRT.JetBlueColumn("Prnom", ColumnType.Text, ColumnFlags.NotNull));
listcolumns.Add(new JetBlue.WinRT.JetBlueColumn("Age", ColumnType.Int32, ColumnFlags.NotNull));
listcolumns.Add(new JetBlue.WinRT.JetBlueColumn("PicturePath", ColumnType.Text, ColumnFlags.NotNull));
listcolumns.Add(new JetBlue.WinRT.JetBlueColumn("Description", ColumnType.Text, ColumnFlags.NotNull));
listcolumns.Add(new JetBlue.WinRT.JetBlueColumn("itemContent", ColumnType.LongText, ColumnFlags.MaybeNull));
var table = db.CreateTable("TETable", listcolumns);
Code C++/CX
Platform::Collections::Vector<JetBlueColumn^>^ listcolumns = ref new Platform::Collections::Vector<JetBlueColumn^>();
listcolumns->Append(ref new JetBlueColumn("Nom", ColumnType::Text, ColumnFlags::NotNull));
listcolumns->Append(ref new JetBlueColumn("Prnom", ColumnType::Text, ColumnFlags::NotNull));
listcolumns->Append(ref new JetBlueColumn("Age", ColumnType::Int32, ColumnFlags::NotNull));
listcolumns->Append(ref new JetBlueColumn("PicturePath", ColumnType::Text, ColumnFlags::NotNull));
listcolumns->Append(ref new JetBlueColumn("Description", ColumnType::Text, ColumnFlags::NotNull));
listcolumns->Append(ref new JetBlueColumn("itemContent", ColumnType::LongText, ColumnFlags::MaybeNull));
auto table = db->CreateTable("TETable", listcolumns);
Code Javascript
var listcolumns = [];
listcolumns.push(new JetBlue.WinRT.JetBlueColumn("Nom", JetBlue.WinRT.Enum.ColumnType.text, JetBlue.WinRT.Enum.ColumnFlags.notNull));
listcolumns.push(new JetBlue.WinRT.JetBlueColumn("Prnom", JetBlue.WinRT.Enum.ColumnType.text, JetBlue.WinRT.Enum.ColumnFlags.notNull));
listcolumns.push(new JetBlue.WinRT.JetBlueColumn("Age", JetBlue.WinRT.Enum.ColumnType.int16, JetBlue.WinRT.Enum.ColumnFlags.notNull));
listcolumns.push(new JetBlue.WinRT.JetBlueColumn("PicturePath", JetBlue.WinRT.Enum.ColumnType.text, JetBlue.WinRT.Enum.ColumnFlags.notNull));
listcolumns.push(new JetBlue.WinRT.JetBlueColumn("Description", JetBlue.WinRT.Enum.ColumnType.text, JetBlue.WinRT.Enum.ColumnFlags.notNull));
listcolumns.push(new JetBlue.WinRT.JetBlueColumn("itemContent", JetBlue.WinRT.Enum.ColumnType.longText, JetBlue.WinRT.Enum.ColumnFlags.maybeNull));
var table = db.createTable("TETable", listcolumns);
To define a column we use here the three following parameters:
-
- Name : String for the table’s name.
- ColumnType : Column’s type
- Bit : Store Boolean value (true/false)
- Int16 : A 2-byte signed integer that can take on values between -32768 and 32767.
- Int32 : 4-byte signed integer that can take on values between - 2147483648 and 2147483647.
- Int64 : An 8-byte signed integer that can take on values between - 9223372036854775808 and 9223372036854775807.
- UInt16 : A 2-byte unsigned integer that can take on values between 0 and 65535.
- UInt32 : A 4-byte unsigned integer that can take on values between 0 (zero) and 4294967295.
- IEEESingle : A single-precision (4-byte) floating point number
- IEEEDouble : A double-precision (8-byte) floating point number
- Text : A fixed or variable length text column that can be up to 255 ASCII characters in length or 127 Unicode characters in length.
- LongText : A fixed or variable length, text column that can be up to 2147483647 ASCII characters in length or 1073741823 Unicode characters in length
- LongBinary : A fixed or variable length, raw binary column that can be up to 2147483647 bytes in length
- DateTime : A double-precision (8-byte) floating point number that represents a date in fractional days since the year 1900.
Remark: in the next version I will add currency and GUID type
-
- ColumnFlags : A group of bits that contain the options for this structure, and which include zero or more of the following values.
- Fixed : The column is fixed. It will always use the same amount of space in a row, regardless of how much data is being stored in the column. cannot be used with Tagged. This bit cannot be used with long values such as LongText and LongBinary.
- Tagged : The column is tagged. Tagged columns do not take up any space in the database if they do not contain data
- MultiValued : The column can be multi-valued. A multi-valued column can have zero, one, or more values associated with it.
- NotNull : The column must never be set to a NULL value.
- MaybeNull : May be null
- Compressed : data in the column can be compressed
- ColumnFlags : A group of bits that contain the options for this structure, and which include zero or more of the following values.
Note : The JetBlueColumn contain other parameters like one to create index. I will show you how to in a next post
Storing data
To store data, use again a collection of JetBlueColumn, containing the values that you want to store, as shown in the samples below
Code VB
listcolumns(0).Value = "Catuhe"
listcolumns(1).Value = "David"
listcolumns(2).Value = 36 'par dfaut, le CLR .NET encode un Object en INT32
listcolumns(3).Value = "https://i.msdn.microsoft.com/ms348103.davidPic(fr-fr,MSDN.10).jpg"
listcolumns(4).Value = "Responsable des experts techniques"
listcolumns(5).Value = "Expert dans les technologies 3D, DirectX OpenGL et tout le toutime"
m_engine.BeginTransation()
table.Records.Add(listcolumns)
listcolumns(0).Value = "Verni"
listcolumns(1).Value = "Eric"
listcolumns(2).Value = 48
listcolumns(3).Value = "https://i.msdn.microsoft.com/ms348103.ericPic(fr-fr,MSDN.10).jpg"
listcolumns(4).Value = "Expert Technique"
listcolumns(5).Value = "Expert dans les technologies Windows, par trs bon en Javascript"
table.Records.Add(listcolumns)
m_engine.CommitTransaction(CommitTransactionFlags.CommitLazyFlush)
Code C#
listcolumns[0].Value = "Catuhe";
listcolumns[1].Value = "David";
listcolumns[2].Value = 36;
listcolumns[3].Value = "https://i.msdn.microsoft.com/ms348103.davidPic(fr-fr,MSDN.10).jpg";
listcolumns[4].Value = "Responsable des experts techniques";
listcolumns[5].Value = "Expert dans les technologies 3D, DirectX OpenGL et tout le toutime";
m_engine.BeginTransation();
table.Records.Add(listcolumns);
listcolumns[0].Value = "Verni";
listcolumns[1].Value = "Eric";
listcolumns[2].Value = 48;
listcolumns[3].Value = "https://i.msdn.microsoft.com/ms348103.ericPic(fr-fr,MSDN.10).jpg";
listcolumns[4].Value = "Expert Technique";
listcolumns[5].Value = "Expert dans les technologies Windows, par trs bon en Javascript";
table.Records.Add(listcolumns);
m_engine.CommitTransaction(CommitTransactionFlags.CommitLazyFlush);
Code C++/CX
listcolumns->GetAt(0)->Value = "Catuhe";
listcolumns->GetAt(1)->Value = "David";
listcolumns->GetAt(2)->Value = 36;
listcolumns->GetAt(3)->Value = "https://i.msdn.microsoft.com/ms348103.davidPic(fr-fr,MSDN.10).jpg";
listcolumns->GetAt(4)->Value = "Responsable des experts techniques";
listcolumns->GetAt(5)->Value = "Expert dans les technologies 3D, DirectX OpenGL et tout le toutime";
m_engine->BeginTransation();
table->Records->Add(listcolumns);
listcolumns->GetAt(0)->Value = "Verni";
listcolumns->GetAt(1)->Value = "Eric";
listcolumns->GetAt(2)->Value = 48;
listcolumns->GetAt(3)->Value = "https://i.msdn.microsoft.com/ms348103.ericPic(fr-fr,MSDN.10).jpg";
listcolumns->GetAt(4)->Value = "Expert Technique";
listcolumns->GetAt(5)->Value = "Expert dans les technologies Windows, par trs bon en Javascript";
table->Records->Add(listcolumns);
m_engine->CommitTransaction(CommitTransactionFlags::CommitLazyFlush);
Code Javascript
listcolumns[0].value = "Catuhe";
listcolumns[1].value = "David";
listcolumns[2].value = -36;
listcolumns[3].value = "https://i.msdn.microsoft.com/ms348103.davidPic(fr-fr,MSDN.10).jpg";
listcolumns[4].value = "Responsable des experts techniques";
listcolumns[5].value = "Expert dans les technologies 3D, DirectX OpenGL et tout le toutime";
m_engine.beginTransation();
table.records.add(listcolumns);
listcolumns[0].value = "Verni";
listcolumns[1].value = "Eric";
listcolumns[2].value = 48;
listcolumns[3].value = "https://i.msdn.microsoft.com/ms348103.ericPic(fr-fr,MSDN.10).jpg";
listcolumns[4].value = "Expert Technique";
listcolumns[5].value = "Expert dans les technologies Windows, par trs bon en Javascript";
table.records.add(listcolumns);
m_engine.commitTransaction(JetBlue.WinRT.Enum.CommitTransactionFlags.commitLazyFlush);
We use here the Value property. This property is an Object, wich means that it can contain any type of data from Integer to String, except a raw array of bytes. For this last type of data, use the BinaryValue instead as we will see in the next post.
Pro and cons using an object as internal type.
Pro: Only one property is use to store data and not a bunch of properties for each type of data (ie, int16, Int32, DateTime etc.)
I use an internal mechanism to cast from object to the appropriate type. This allows a simpler use of the component
Cons: By defaultThe CLR or the WinRT store the 48 constant as an INT32, this is not a problem if you use an ColumnType.Int32, like we do in our sample. But if you you want a ColumnType.Int64 instead, the engine throw an “Invalid Type” exception.
To fix the problem cast the Value (.ie JetBlueColumn.Value=(Int64)48).
For Javascript, it’s the same problem, except, it use by default a Double (number) and there are no way to cast in Javascript. It’s the reason why, you need to precise the usewithjavascript to true when initializing the engine. Doing that, I’m be able to treat this special case, and use internal algorithm only for this language.
To add a record to the the table, use the void Add(IVector<JetBlueColumn^> ^record)
Of course you can Update or Remove record, with the appropriate method. void Update(IVector<JetBlueColumn ^> ^record) /void Remove()
Navigating into a cursor
A basic navigation into a cursor is sequentially
Code VB
Dim t1 = db.OpenTable("TETable", JetBlue.WinRT.Enum.OpenTableFlags.ReadOnly)
Dim columns = New List(Of JetBlueColumn)
columns.Add(New JetBlueColumn("Nom"))
columns.Add(New JetBlueColumn("Prnom"))
columns.Add(New JetBlueColumn("Age"))
columns.Add(New JetBlueColumn("PicturePath"))
columns.Add(New JetBlueColumn("Description"))
columns.Add(New JetBlueColumn("itemContent"))
Dim count As Integer = 1000
Do
Dim record = t1.Records.Get(columns)
Dim name = record(1).Value + " " + record(0).Value
Dim subtitle = record(4).Value.ToString()
Dim picturePath = record(3).Value.ToString()
Dim content = record(5).Value.ToString()
group1.Items.Add(New SampleDataItem("Group-1-Item-1" + count.ToString(),
name,
subtitle,
picturePath,
content,
content,
group1))
count += 1
Loop While t1.Records.Move(JetBlue.WinRT.Enum.MoveDirection.Next) = JetBlue.WinRT.Enum.MoveResult.Success
Code C#
var t1 = db.OpenTable("TETable", OpenTableFlags.ReadOnly);
var columns = new List<JetBlueColumn>();
columns.Add(new JetBlueColumn("Nom"));
columns.Add(new JetBlueColumn("Prnom"));
columns.Add(new JetBlueColumn("Age"));
columns.Add(new JetBlueColumn("PicturePath"));
columns.Add(new JetBlueColumn("Description"));
columns.Add(new JetBlueColumn("itemContent"));
int count = 1000;
do
{
var record = t1.Records.Get(columns);
var name = record[1].Value + " " + record[0].Value;
var subtitle = record[4].Value.ToString();
var picturePath = record[3].Value.ToString();
var content = record[5].Value.ToString();
group1.Items.Add(new SampleDataItem("Group-1-Item-1" + count.ToString(),
name,
subtitle,
picturePath,
content,
content,
group1));
count += 1;
}
while (t1.Records.Move(MoveDirection.Next) != MoveResult.NoCurrentRecord);
Code C++/CX
auto t1 = db->OpenTable("TETable", JetBlue::WinRT::Enum::OpenTableFlags::ReadOnly);
auto columns=ref new Platform::Collections::Vector<JetBlueColumn^>();
columns->Append(ref new JetBlueColumn("Nom"));
columns->Append(ref new JetBlueColumn("Prnom"));
columns->Append(ref new JetBlueColumn("Age"));
columns->Append(ref new JetBlueColumn("PicturePath"));
columns->Append(ref new JetBlueColumn("Description"));
columns->Append(ref new JetBlueColumn("itemContent"));
int count = 1000;
do
{
auto record = t1->Records->Get(columns);
auto name = record->GetAt(1)->Value + " " + record->GetAt(0)->Value;
auto subtitle = record->GetAt(4)->Value->ToString();
auto picturePath = record->GetAt(3)->Value->ToString();
auto content = record->GetAt(5)->Value->ToString();
group1->Items->Append(ref new SampleDataItem("Group-1-Item-1" + count.ToString(),
name,
subtitle,
picturePath,
content,
content,
group1));
count += 1;
}
while (t1->Records->Move(JetBlue::WinRT::Enum::MoveDirection::Next) != JetBlue::WinRT::Enum::MoveResult::NoCurrentRecord);
Code Javascript
var t1 = db.openTable("TETable", JetBlue.WinRT.Enum.OpenTableFlags.readOnly);
var columns = [];
columns.push(new JetBlue.WinRT.JetBlueColumn("Nom"));
columns.push(new JetBlue.WinRT.JetBlueColumn("Prnom"));
columns.push(new JetBlue.WinRT.JetBlueColumn("Age"));
columns.push(new JetBlue.WinRT.JetBlueColumn("PicturePath"));
columns.push(new JetBlue.WinRT.JetBlueColumn("Description"));
columns.push(new JetBlue.WinRT.JetBlueColumn("itemContent"));
do {
var record = t1.records.get(columns);
var name = record[1].value + " " + record[0].value;
sampleItems.push({ group: sampleGroups[0], title: name, subtitle: record[4].value, description: record[5].value, content: record[2].value, backgroundImage: record[3].value });
}
while (t1.records.move(JetBlue.WinRT.Enum.MoveDirection.next) != JetBlue.WinRT.Enum.MoveResult.noCurrentRecord);
First we open a table with the JetBlueTable^ OpenTable(Platform::String^ tablename,OpenTableFlags flags) method with the ReadOnly Flag.
Then we use again, a collection of JetBlueColumn, with the names of the columns that you want to retrieve the data.
The IVector<JetBlueColumn^>^ Get(IVector<JetBlueColumn ^>^ columns) method, takes this collection as a parameter. Then to display the data use the Value property from the JetBlueColumn object.
To move on the cursor, use the MoveResult Move(MoveDirection direction) in a loop while testing the availability of record (NoCurrentRecord)
Remark: Like a SQL query, be careful with the number of the columns you use. In this sample is more like a “select * from TETable” and not really recommended.
When there are many records in the table, scanning all the table is not a best practice. It’s better to use an incremental mechanism. For that, you can use the IVector<IVector<JetBlueColumn^>^>^ Get(IVector<JetBlueColumn^> ^columns,unsigned int recordperpage) overloaded method, wich take the number of records you want on one call. This is also an effective way , because moving into the cursor (Move (Next)), remains within the boundaries of the component and avoids go them and return between the borders of Javascript, VB and c# languages.
Code VB
Dim records = t1.Records.Get(columns, 5)
For Each record In records
Dim name = record(1).Value + " " + record(0).Value
Dim subtitle = record(4).Value.ToString()
Dim picturePath = record(3).Value.ToString()
Dim content = record(5).Value.ToString()
group1.Items.Add(New SampleDataItem("Group-1-Item-1" + count.ToString(),
name,
subtitle,
picturePath,
content,
content,
group1))
count += 1
Next
Code C#
var records = t1.Records.Get(columns, 5);
foreach (var record in records)
{
var name = record[1].Value + " " + record[0].Value;
var subtitle = record[4].Value.ToString();
var picturePath = record[3].Value.ToString();
var content = record[5].Value.ToString();
group1.Items.Add(new SampleDataItem("Group-1-Item-1" + count.ToString(),
name,
subtitle,
picturePath,
content,
content,
group1));
count += 1;
}
Code C++/CX
auto records=t1->Records->Get(columns,5);
int count=0;
for each (auto record in records)
{
auto name = record->GetAt(1)->Value + " " + record->GetAt(0)->Value;
auto subtitle = record->GetAt(4)->Value->ToString();
auto picturePath = record->GetAt(3)->Value->ToString();
auto content = record->GetAt(5)->Value->ToString();
group1->Items->Append(ref new SampleDataItem("Group-1-Item-1" + count.ToString(),
name,
subtitle,
picturePath,
content,
content,
group1));
count += 1;
}
Code Javascript
var records = t1.records.get(columns, 5);
records.forEach(function (record) {
var name = record[1].value + " " + record[0].value;
sampleItems.push({ group: sampleGroups[0], title: name, subtitle: record[4].value, description: record[5].value, content: record[5].value, backgroundImage: record[3].value });
});
DataArrived(sampleItems);
For a reactive interface, most of the WinRT API are asynchrone, you can also use the asynchrone methods, instead of the synchrone one
IAsyncOperation<IVector<IVector<JetBlueColumn^>^>^>^ GetAsync(IVector<JetBlueColumn^> ^columns, unsigned int recordperpage)
Code Javascript
t1.records.getAsync(columns, 10).then(function (records) {
records.forEach(function (record) {
var name = record[1].value + " " + record[0].value;
sampleItems.push({ group: sampleGroups[0], title: name, subtitle: record[4].value, description: record[5].value, content: record[5].value, backgroundImage: record[3].value });
});
DataArrived(sampleItems);
t1.close;
db.close;
m_engine.endSession();
});
Code C++/CX
task<IVector<IVector<JetBlueColumn^>^>^> taskGet(t1->Records->GetAsync(columns,100));
taskGet.then([this,group1,t1,db,m_engine](IVector<IVector<JetBlueColumn^>^>^ records)
{
int count=0;
for each (auto record in records)
{
auto name = record->GetAt(1)->Value + " " + record->GetAt(0)->Value;
auto subtitle = record->GetAt(4)->Value->ToString();
auto picturePath = record->GetAt(3)->Value->ToString();
auto content = record->GetAt(5)->Value->ToString();
group1->Items->Append(ref new SampleDataItem("Group-1-Item-1" + count.ToString(),
name,
subtitle,
picturePath,
content,
content,
group1));
count += 1;
}
t1->Close();
db->Close();
m_engine->EndSession();
},task_continuation_context::use_current());
You can get also asynchronously, record by record using theIAsyncActionWithProgress <IVector<JetBlueColumn^>^>^ GetWithProgressionAsync(IVector<JetBlueColumn^> ^columns) method
Code Javascript
var index = 0;
t1.records.getWithProgressionAsync(columns).then(function () {
t1.close;
db.close;
m_engine.endSession();
}, function (error) {
}, function (record) {
var name = record[1].value + " " + record[0].value;
sampleItems.push({ group: sampleGroups[0], title: name, subtitle: record[4].value, description: record[5].value, content: record[5].value, backgroundImage: record[3].value });
ItemArrived(sampleItems, index);
index += 1;
});
In the next post we will see :
- How to create a table with indexes.
- How to use indexes in a query
- How to store picture as a bytes array
Eric
Comments
- Anonymous
January 29, 2015
The comment has been removed