First lets make one thing clear: “No I’m not chasing Google Chrome versioning!” The reason is that I’m trying to follow Semantic versioning and if there is a change that makes SisoDb more flexible and more performant and it has been asked for, it will go into the codebase. I try to have frequent releases and if it’s a braking change, major version is bumped.
Before going into the meat and the reason for why version 9.0 has been released, lets look at some other stuff. For source code, documentation etc, go to: http://sisodb.com
Denali
The SQL 2008 provider has now been tested against Sql-Server 2012 Express RC0 (Denali) and it works. There will be a separate provider “SisoDb.Sql2012″ for this, but if you want to jumpstart, e.g trying out LocalDb features, you can.
Version 9.0, the Changes
This new version, v9.0, has had two major focus areas:
- New layout in database for indexes-values
- Adapt API for coming providers not having Transactions
New layout in database for indexes-values
One major focus has been to rewrite how the key-values that are used for queries, are stored. This is the result of feedback from the community. And as a step in gaining better querying performance, each Indexes table has been divided up amongst seven tables, grouping data that is of the samy type together. By doing this more effective indexes can be designed for enhancing queries and at the same time retain insert speed. I know it sounds like a lot of tables, but hey, Siso should keep you out of the database. And for you that are afraid of limitations, you can read here (http://msdn.microsoft.com/en-us/library/ms143432.aspx), that tables counts as objects and the total number of all objects in a SQL2008 database is as high as 2,147,483,647 objects.
More to come for queries and inserts
There’s plans for making it possible for you to hook in a caching implementation, so that queries doesn’t have to touch the database. In forthcoming release, there will be focus on moving the process of inserting values into the Indexes-tables to a background process. Hence upon inserting items, the structure (document) will be inserted transactional and then the indexes will be queued and inserted in the background. Having done this partitioning by dividing each Indexes-table up in several tables, it will be easier to accomplish parallel inserts.
Text vs String
When you design your model and use properties with string, there’s now from version 9 two different strings. Either you use the normal string BCL type or the custom Text type found in SisoDb. Values from the former will end up in [Entity]Strings table and the later in [Entity]Texts table. Strings has a max length of 300 chars while Text doesn’t. This semantic separation is done so that effective indexes for queries could be created for normal strings, which isn’t feasible if it would be nvarchar(max).
The Text type in SisoDb is implicit convertible to and from a string so you don’t have to use it explicitly other than as a marker on your entity property.
Sample
public class BlogPost
{
public Guid Id { get; set; }
public string Title { get; set; } //Ends up in BlogPostStrings
public Text Content { get; set; } //Ends up in BlogPostTexts
}
var post = new BlogPost
{
Title = "A title of max 300 chars",
Content = "Some long text that can exceed 300 chars."
}
Adapt API for coming providers not having Transactions
In coming realeases, v9.x, SisoDb will have providers that hasn’t support for transactions like the RDBMS environment does. Having UnitOfWork and UnitOfWork.Commit in these providers will not make sense and will probably lead to confusion. Therefore UnitOfWork has changed its name to WriteSession and the QueryEngine is now named ReadSession. Furthermore the UnitOfWork.Commit() method has been removed and auto commit behavior is instead used on UnitOfWork.Dispose(), hence UnitOfWork will still be transactional when you target e.g Sql2008 and SqlCe4. Note!A commit will only be performed if no exception has been encountered.
Old code
using(var unitOfWork = db.CreateUnitOfWork())
{
unitOfWork.Insert(x);
unitOfWork.Insert(y);
unitOfWork.Update(z);
unitOfWork.Commit();
}
using(var q = db.CreateQueryEngine())
{
var r = q.Query<Customer>().Where(c => c.CustomerNo == "123456").SingleOrDefault();
}
New code
//As long as the underlying provider supports it, a Write session is still transactional.
using(var session = db.BeginWriteSession())
{
session.Insert(x);
session.Insert(y);
session.Update(z);
} //A Write session is implicitly being committed on Dispose().
using(var q = db.BeginReadSession())
{
var r = q.Query<Customer>().Where(c => c.CustomerNo == "123456").SingleOrDefault();
}
Other changes
There has also been some other minor adjustments for v9.0 and since SisoDb has evolved kind of rapid lately, chances are that you have missed some features and changes of earlier releases, hence some of them are covered below as well.
DbSchemaNamingPolicy
You can now control the global naming of your structures by register a specific Func against the static DbSchemaNamingPolicy class:
DbSchemaNamingPolicy.StructureNameGenerator =
schema => return string.Concat("MyPrefix", schema.Name);
UpdateMany
UpdateMany has been rebuilt to take care of update many operations and not migration operations. As a step, you now have to provide a predicate and UpdateManyStatuses isn’t used anymore to control if an item should be kept or not. Also, the UpdateMany method of the UnitOfWork (now WriteSession) taking an old type and an new type has been removed. To get this functionality there’s a DbStructureSetMigrator you can use instead.
var migrator = Database.GetStructureSetMigrator();
migrator.Migrate<ModelComplexUpdates.Person, ModelComplexUpdates.SalesPerson>((p, sp) =>
{
var names = p.Name.Split(' ');
sp.Firstname = names[0];
sp.Lastname = names[1];
var address = p.Address.Split(
new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
sp.Office.Street = address[0];
sp.Office.Zip = address[1];
sp.Office.City = address[2];
return StructureSetMigratorStatuses.Keep;
});
Custom non generic collections
Actually, this was released as a patch to v8 but I thought it was worth mentioning. As of now you can have custom, non-generic collections.
public class MyModel
{
public Guid Id { get; set; }
public MyCollection Items { get; set; }
}
public class MyItem
{
public int Value { get; set; }
}
public class MyCollection : List<MyItem> {}
Custom naming of the Id-property
To clean up your models as of v8 you are not forced to name the Id-property “StructureId”. It will look for the following names:
- StructureId
- [TypeName]Id
- Id
- I[InterfaceName]Id
Machine name specific connectionstrings
This is also a v8 feature and you can now have connectionstring names prefixed with a machine name. When providing a connection string name, Siso will first try to find one with the value you pass but prefixed with Machine name_.
So if you pass “MyConnectionStringName” it will try and find:
- MachineName_MyConnectionStringName
- MyConnectionStringName
Case-sensitive collations
I have tested it against a database with a case-sensitive collation setting, and all tests now passes. There was some SQL where members where written in wrong casing but that has now been fixed.
Removed fields
To make the database schema more friendly for manual updates, the hashed value representing an entity has been removed. The SQL queries has also been rewritten so that the RowId columns no longer is needed.
Misc
There has also been some correction of bugs and performance tweaks, regarding some parallel generation of Id’s, structures etc.
Migrate
Take a backup of your database before porting! Below is some info about the changes made to the storage layout, which could be useful. For more info just contact me.
SisoDbIdentities table
The EntityHash column has been dropped and primary-key is instead EntityName. New layout is:

Structures tables
The RowId column and any associated index has been dropped. New layout is:

Indexes tables
You should be able to just make the adjustments to the other tables and then re-save the structures. That should generate the new indexes tables and put values in them. But again. Be ensured you do have a backup.
For manual porting
The values from the indexes tables needs to be inserted in each dedicated indexes-table. Soo values stored in e.g CustomerIndexes IntegerValue column should be stored in CustomerIntegers Value column. Note! That all values (depending on version of SisoDb) has a representation of it’s value in the StringValue column. Hence, when moving values from the StringValue column to CustomerStrings or CustomerTexts you should only move the once that represents a string, which should be the once that has null in every other value column.
Uniques tables
As with the Indexes tables, if you drop this table and re-save all structures the table should be recreated and populated in the correct manners.
Other than that the only change that has been made is that the RowId column has been dropped. New layout is:

That’s it.
//Daniel
