SisoDb v9.0 Released.

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

8 thoughts on “SisoDb v9.0 Released.

  1. Pingback: The Morning Brew - Chris Alcock » The Morning Brew #1024

    • Thanks!

      No public application no. I’m putting together a sample with some CQRS flavor in it, where I will show how to use SisoDb for the readstore and the eventstore.

      //Daniel

  2. I think you need use cases listed. E.g. scenarios where SisoDb can be useful vs. not.
    I can see it can be useful in logging.

  3. Daniel,

    Thank you, I have been wanting to do NoSql for some time, but wanted a solution to leverage MS SQL. One that does not require two data storages.

    I’m working on a real world implementation converting a quick and dirty implementation using binary serialization.

    It took me all of about 4 hours to covert my application from Binary Serialization and BLOBS to SiSoDB.

    One good real world example is when you work with a document in real life. My line of work is insurance and a policy is a document. Using a Document or Structure DB is perfect fit.

    Because SiSoDB uses SQL I’m also able to leverage ASP.Net membership and other RDBMS features for managing users/agents and rating tables. This is an online insurance app, but it is an Extranet/B2B.

    The only thing that I had a problem with was a cyclic issue. I had to restructure the business entity objects and some repositories. I had a relation similar Parent -> Children with the Children having a property back to the parent Child -> Parent. I know it is not an issue SiSoDB, but with PineCone and maybe TypeSerializer. I only got as far as getting the source code for PineCone and stepped through an infinate loop.

    GB

    • Hi,

      positioning SisoDb as NoSql or not, glad that it solves a problem for you in your use-case.

      Regarding the Parent-Child-Parent issue, I will have a look at PineCone. I have never had the need for this case, hence not yet supported. I do know that the ServiceStack JSON-serializer recently got a fix for this (not sure what version). I will have a look and try to fix it soon.

      //Daniel

  4. Pingback: Ranting is good for you « Daniel Wertheim

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s