We are very excited to announce today support for 3 extra platforms by our database engine: MonoTouch, MonoDroid and CompactFramework.
Siaqodb on MonoTouch
Since release of first version of Siaqodb we was interested to port on MonoTouch because of high community interests for this platform, but we postpone a bit because of some reasons, mainly because of limitations this platform has. Because Apple not allow JIT-ing on iOS, MonoTouch use AOT compilation and as consequence there are some important limitations that keep us away for some time.
Siaqodb usually “translates” a LINQ Expression tree into “internal language” so engine returns data queried in optimized way, but some LINQ queries cannot be optimized or it is needed to generate code at runtime based on LINQ Expression and in this case we call expression.Compile() and then apply that predicate(usually) over objects stored in DB. Main problem is that expression.Compile() generate code at runtime and this is not allowed by MonoTouch. Luckily we managed to optimize most of LINQ expression types and hopefully we can offer to developer workarounds by providing a equivalent LINQ query for the non-working one.
But in general we found that besides limitations, Siaqodb offer best API for a database on MonoTouch today, LINQ optimized queries, indexes, transactions…and performance is very close to native .NET app.
Here is a picture with Siaqodb running on iOS device:

siaqodb on iOS
And here is UI source code:
namespace SiaqodbMTDemo
{
public class Application
{
static void Main (string[] args)
{
UIApplication.Main (args);
}
}
// The name AppDelegate is referenced in the MainWindow.xib file.
public partial class AppDelegate : UIApplicationDelegate
{
SharedBusinessLayer.PersonManager personManager;
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
window.MakeKeyAndVisible ();
string dbPath= Environment.GetFolderPath (Environment.SpecialFolder.Personal);
SharedBusinessLayer.SiaqodbFactory.SetDBName(dbPath);
personManager = new SharedBusinessLayer.PersonManager();
button.TouchDown+=delegate { PopulateDatabase(); };
txtSearch.SearchButtonClicked+=delegate { this.Search(this.txtSearch.Text); };
return true;
}
private void PopulateDatabase()
{
personManager.PopulateDatabase();
IList<Person> persons = personManager.GetAllPersons();
this.tableView.Source = new TableViewDataSource(persons);
this.tableView.ReloadData();
}
private void Search(string filterString)
{
var queryResult = personManager.GetPersonsFiltered(filterString);
this.tableView.Source = new TableViewDataSource(queryResult.ToList());
this.tableView.ReloadData();
}
private class TableViewDataSource : UITableViewSource
{
static NSString kCellIdentifier =new NSString ("MyIdentifier");
private IList<Person> list;
public TableViewDataSource (IList<Person> list)
{
this.list = list;
}
public override int RowsInSection (UITableView tableview, int section)
{
return list.Count;
}
public override UITableViewCell GetCell ( UITableView tableView, NSIndexPath indexPath)
{
UITableViewCell cell =tableView.DequeueReusableCell (kCellIdentifier);
if (cell == null)
{
cell = new UITableViewCell (UITableViewCellStyle.Default,kCellIdentifier);
}
cell.TextLabel.Text = list[indexPath.Row].ToString();
return cell;
}
}
}
What is cool using Siaqodb is that you can share the Code between all platforms, in our examples projects we use SharedBusinessLayer assembly as shared assembly for all our examples:MonoTouch, MonoAndroid, Silverlight, WindowsPhone7 and CompactFramewok. Only difference is that we have a separate .csproj file that target each specific platform. So here is code of PersonManager class from SharedBusinessLayer assembly:
namespace SharedBusinessLayer
{
public class PersonManager
{
Siaqodb siaqodb;
string lastNames = @"CUNNINGHAM,BRADLEY,LANE,ANDREWS,RUIZ,HARPER,FOX,RILEY,ARMSTRONG,CARPENTER,WEAVER,GREENE,LAWRENCE,ELLIOTT,CHAVEZ,SIMS,AUSTIN,PETERS,KELLEY,FRANKLIN,LAWSON,FIELDS,GUTIERREZ,RYAN,SCHMIDT,CARR,VASQUEZ,CASTILLO,WHEELER,CHAPMAN,OLIVER,MONTGOMERY,RICHARDS,WILLIAMSON,JOHNSTON,BANKS,MEYER,BISHOP,MCCOY,HOWELL,ALVAREZ,MORRISON,HANSEN,FERNANDEZ,GARZA,HARVEY,LITTLE,BURTON,STANLEY,NGUYEN,GEORGE,JACOBS,REID,KIM,FULLER,LYNCH,DEAN,GILBERT,GARRETT,ROMERO,WELCH,LARSON,FRAZIER,BURKE,HANSON,DAY,MENDOZA,MORENO,BOWMAN,MEDINA,FOWLER,BREWER,HOFFMAN,CARLSON,SILVA,PEARSON,HOLLAND,DOUGLAS,FLEMING,JENSEN,VARGAS,BYRD,DAVIDSON,HOPKINS,MAY,TERRY,HERRERA,WADE,SOTO,WALTERS,CURTIS,NEAL,CALDWELL,LOWE,JENNINGS,BARNETT,GRAVES,JIMENEZ,HORTON,SHELTON";
string firstNames = @"HAL,BRAIN,ROB,ELWOOD,KENDRICK,DARIUS,MOISES,SON,MARLIN,FIDEL,THADDEUS,CLIFF,MARCEL,ALI,JACKSON,RAPHAEL,BRYON,ARMAND,ALVARO,JEFFRY,DANE,JOESPH,THURMAN,NED,SAMMIE,RUSTY,MICHEL,MONTY,RORY,FABIAN,REGGIE,MASON,GRAHAM,KRIS,ISAIAH,VAUGHN,GUS,AVERY,LOYD,DIEGO,ALEXIS,ADOLPH,NORRIS,MILLARD,ROCCO,GONZALO,DERICK,RODRIGO,GERRY,STACEY,CARMEN,WILEY,RIGOBERTO,ALPHONSO,TY,SHELBY,RICKIE,NOE,VERN,BOBBIE,REED,JEFFERSON,ELVIS,BERNARDO,MAURICIO,HIRAM,DONOVAN,BASIL,RILEY,OLLIE,NICKOLAS,MAYNARD,SCOT,VINCE,QUINCY,EDDY,SEBASTIAN,FEDERICO,ULYSSES,HERIBERTO,DONNELL,COLE,DENNY,DAVIS,GAVIN,EMERY,WARD,ROMEO,JAYSON,DION,DANTE,CLEMENT,COY,ODELL,MAXWELL,JARVIS,BRUNO,ISSAC,MARY,DUDLEY";
Random random = new Random();
public PersonManager()
{
siaqodb = SiaqodbFactory.GetInstance();
}
public IList<Person> GetAllPersons()
{
return siaqodb.LoadAll<Person>();
}
public void PopulateDatabase()
{
string[] lastNamesArr = lastNames.Split(',');
string[] firstNamesArr = firstNames.Split(',');
for (int i = 0; i < 50; i++)
{
Person person = new Person();
person.LastName = lastNamesArr[random.Next(100)];
person.FirstName = firstNamesArr[random.Next(100)];
person.Age = random.Next(18, 50);
person.Married = (i % 2 == 0);
siaqodb.StoreObject(person);
}
siaqodb.Flush();
}
public string filterString;
public IEnumerable<Person> GetPersonsFiltered(string filter)
{
this.filterString = filter;
var query = from Person pers in siaqodb
where pers.FirstName.Contains(filterString) || pers.LastName.Contains(filterString)
select pers;
return query;
}
public void Save(Person person)
{
siaqodb.StoreObject(person);
}
public void Delete(Person person)
{
siaqodb.Delete(person);
siaqodb.Flush();
}
public void Flush()
{
siaqodb.Flush();
}
}
}
About SyncFramework provider for MonoTouch version, we just want to let developers know that port is in progress and as soon SyncFramework 4.0 license allow using it in production, we will release also the SyncProvider.
About limitations… bellow we will try to give some examples that NOT work on MonoTouch but we can offer alternatives:
1.Use of a local method inside LINQ:
from Customer c in siaqodb where c.NrEmployees==GetNrEmployees() select c;
This query will crash when you will run on iOS device, but you can use a local variable that gets method returned value and then use this variable inside LINQ:
int nrEmp= GetNrEmployees(); from Customer c in siaqodb where c.NrEmployees==nrEmp select c;
This will work fine.
2.call methods/properties of stored object members inside LINQ queries:
from Customer c in siaqodb where c.Name.Length>10 select c;
Will crash on iOS device, siaqodb can only optimize following methods of members and only of string type members: StartsWith, EndsWith, Contains all the other methods of properties/members of stored objects call will result in a crash.
3.Unary !(not) operator use; following LINQ query:
from Customer c in siaqodb where !c.Dismissed select c;
Will crash, use instead equality operator like:
from Customer c in siaqodb where c.Dismissed==false select c;
This will work fine!
In general what is not allowed inside LINQ queries:
-methods call are not allowed, use instead a local variable and assign method returned value to it and then use that variable inside LINQ query wherever is possible
-methods call of object members other than StartsWith,EndsWith and Contains are not allowed.
-non comparison operators are not allowed, like:…where c.Age+4>30…use instead a local variable wherever is possible
-unary operators like !(not) are not allowed
-select(projection) should use only storable objects or object members, avoid any operations in select like: …select new {Name=c.Name+c.FirstName;}…
-multiple joins are not allowed, use instead 2 queries or appropriate workarounds to join results of 2 queries or so.
Important notice: those examples may work on iPhone/iPad Emulators but NOT work on devices.
About MonoDroid there is not many things changed since latest Beta, so see previous posts about it, about CompactFramework version we will detail more on a next post.
You can download latest versions for all platforms from our download page.
Happy “.NET everywhere”coding!



