Signum Framework Tutorials Part 1 – Southwind Entities
- Download Signum Framework 2.0 Binaries - 2.17 MB (also in codeplex.com)
- Download Signum Framework 2.0 Sources - 1.48 MB (also in github.com)
- Download Southwind Part1 Entities - 165.63 KB (also in github.com)
- Backup of Microsoft Northwind Sample Database (also in microsoft.com)
- Backup of resulting Southwind Database

Content
- About Signum Framework 2.0
- About this series
- Instalation
- Creating the entities
- Out first entity: Region
- Entity with foreign key: Territory
- EmbeddedEntity: Address
- Getting big: Employee entity
- Getting fast: Rest of the entities
- Property Validation
- Southwind.Logic
- Southwind.Load
- Summary
About Signum Framework 2.0
We are pleased to announce that finally we have released Signum Framework 2.0.
The release took more than expected but, as a result, is much more ambitious. We have been using our framework internally in a daily basis and we think that this release is finished and will glad everyone brave enough to use it.
The new release is focused in different trends:
- Signum.Web: Based in ASP.Net MVC 3.0 and Razor, tries to keep the same feeling and productivity of Signum.Windows without constraining the possibilities of the web (jQuery, Ajax, control of the markup, friendly urls…)
- Keeping up to date with technology: The framework now runs only on .Net 4.0/ ASP.Net MVC 3.0 and the snippets and templates target Visual Studio 2010.
- Improving pretty much everything and fixing bugs: For a complete list look at the change log http://www.signumframework.com/ChangeLog2.0.ashx
About this series
In order to show the capabilities of the framework, and have a good understanding of the architecture, we’re preparing a series of tutorials in which we will work on a stable application: Southwind.
Southwind is the Signum version of Northwind, the well-known example database provided with Microsoft SQL Server.
In this series of tutorials we will create the whole application, including the entities, business logic, windows (WPF) and web (MVC) user interface, data loading and any other aspect worth to explain.
If you want to know more about the principles of Signum framework look at the previous tutorial
Time to get our hands dirty with the entities:
Instalation
Signum framework is Open Source (LGPL) and can be downloaded for free in codeplex http://signum.codeplex.com/, the source code is also available in https://github.com/signumframework/signumframework
The installer will copy the following:
- Assemblies: {Program files}\Signum Software\Signum Framework 2.0
- Code Snippets: {Documents}\Visual Studio 2010\Code Snippets\Visual C#\My Code Snippets
- Project template: {Documents}\Visual Studio 2010\Templates\ProjectTemplates\Visual C#
- WPF Control Template: {Documents}\Visual Studio 2010\Templates\ItemTemplates\Visual C#
- ASP.Net MVC 3 Razor Control Template: {Program Files}\Microsoft Visual Studio 10.0\Common7\IDE\ ItemTemplates\CSharp\Web\MVC 3\CodeTemplates\AddView\CSHTML
Once installed, open Visual Studio 2010, and create a new project. Under Visual C#/.Net Framework 4 there’s a new Signum Framework 2.0 Client – Server template. Create a new project called Southwind and a solution with 5 projects should be created:
- Southwind.Entities
- Southwind.Load
- Southwind.Logic
- Southwind.Web
- Southwind.Windows
Unload everything but Southwind.Entities for now, and open MyEntity.cs
Creating the entities
Signum Framework promotes a code-first approach and the entities you write have a straightforward mapping to database tables. Also, since 100% of the SQL queries are produced by the framework, including schema modification, you almost forget about SQL Management Studio.
For teaching, however, will be easier to start by showing what we are trying to accomplish in a familiar diagram. Here is Northwind database:

Out first entity: Region
Let’s start simple. In order to create the entity for Region we need to inherit from IdentifiableEntity class and create the description field.
We will call it Description, not RegionDescription, since this redundancy makes sense only to simplify writing SQL manually (not the case).
Also, we don’t have to worry about RegionID, since every IdentifiableEntity already has Id and ToStr field/property.
We already have the snippets installed so just remove MyEntityDN class and press:
entityWithName [Tab] [Tab] Region [Tab] description [Tab] Description [Enter]
After this, we should have something like this:
[Serializable]
public class RegionDN : Entity
{
[NotNullable, SqlDbType(Size = 100), UniqueIndex]
string description;
[StringLengthValidator(AllowNulls = false, Min = 3, Max = 100)]
public string Description
{
get { return description; }
set { SetToStr(ref description, value, () => Description); }
}
public override string ToString()
{
return description;
}
}
This is our entity class, some things to notice.
The class
The class is Serializable, so you can send it though a web service or save it in a file.
Also, inherits from Entity to enables concurrency support. Since this entity will be changed once in a while by admins, we can change to IdentifiableEntity and save the inherited Tick column.
Finally, notice that we write the name of our entities in singular, as well as the name of the table.
The field
There’s a description field. In Signum Framework entities, every field will generate a database column.
The column will try to match the CLR type whenever possible so in the case of strings it will be Nullable and, by default, a length of 200 characters.
The attributes over the field override some of this defaults, in this case makes the column not nullable and with a length of 100.
Just by placing UniqueIndex attribute, an index will be created over the column.
The property
Every property gives access to the underlying field for the user interface and business logic.
In order to user the property in queries, there have to be a field with the same name but lowercase. Unfortunately VS snippets are not smart enough so you have to repeat the name twice.
By decorating the properties with ValidationAttributes we enforce simple validation rules over the entities. More flexible validation options are available and the attributes can be overridden.
Also we can decorate our properties with other annotations to change the display name, the format of numbers or dates, the unit of the value, etc…
Finally, we can see that the getter of the property is trivial, but the setter calls a protected Set method. This method does the following:
- Set the value of the field to the new value
- Marks the entity as modified (dirty) so is not skipped when saving
- Fires PropertyChanged event so the user interface (if any) gets updated
- Returns true if there was a change, false if the value was the same
Entity with foreign key: Territory
Let’s continue now with Territory:
entityWithName [Tab] [Tab] Territory [Tab] description [Tab] Description [Enter]
We also change the base class to IdentifiableEntity, TerritoryID comes for free but we have to create the RegionID column and the foreign key. Quite simple, just create a property of type Region:
field [Tab] [Tab] RegionDN [Tab] region [Tab] Region [Enter]
Since Territory property is mandatory, let’s add a NotNullValidator over the property. The result should be something like this:
[Serializable]
public class TerritoryDN : Entity
{
RegionDN region;
[NotNullValidator]
public RegionDN Region
{
get { return region; }
set { Set(ref region, value, () => Region); }
}
[NotNullable, SqlDbType(Size = 100), UniqueIndex]
string description;
[StringLengthValidator(AllowNulls = false, Min = 3, Max = 100)]
public string Description
{
get { return description; }
set { SetToStr(ref description, value, () => Description); }
}
public override string ToString()
{
return description;
}
}
The next step should be the EmployeeTerritories relational table, this table however is not an ‘Entity’ but a Many-to-Many relationship between Employees and Territories. In Signum Framework this is represented by a MList<TerritoryDN> field on Employee entity.
EmbeddedEntity: Address
Before getting into Employee table, we can see that some fields (Address, City, Region, PostalCode and Country) are also repeated in Customers, Orders and Supplier tables.
In order to create an address entity that ‘belongs’ to the parent table we have to make it inherit from EmbeddedEntity:
entity [Tab] [Tab] Address [Enter] fieldString [Tab] [Tab] address [Tab] Address [Enter] fieldString [Tab] [Tab] city [Tab] City [Enter] fieldString [Tab] [Tab] region [Tab] Region [Enter] fieldString [Tab] [Tab] postalCode [Tab] PostalCode [Enter] fieldString [Tab] [Tab] county [Tab] Country [Enter]
Now let’s change the base class to EmbeddedEntity and make some changes to the size of the fields (and the corresponding validators) to mimic the Northwind database.
[Serializable]
public class AddressDN : EmbeddedEntity
{
[NotNullable, SqlDbType(Size = 60)]
string address;
[StringLengthValidator(AllowNulls = false, Min = 3, Max = 60)]
public string Address
{
get { return address; }
set { Set(ref address, value, () => Address); }
}
[NotNullable, SqlDbType(Size = 15)]
string city;
[StringLengthValidator(AllowNulls = false, Min = 3, Max = 15)]
public string City
{
get { return city; }
set { Set(ref city, value, () => City); }
}
[NotNullable, SqlDbType(Size = 15)]
string region;
[StringLengthValidator(AllowNulls = false, Min = 3, Max = 15)]
public string Region
{
get { return region; }
set { Set(ref region, value, () => Region); }
}
[NotNullable, SqlDbType(Size = 10)]
string postalCode;
[StringLengthValidator(AllowNulls = false, Min = 3, Max = 10)]
public string PostalCode
{
get { return postalCode; }
set { Set(ref postalCode, value, () => PostalCode); }
}
[NotNullable, SqlDbType(Size = 15)]
string country;
[StringLengthValidator(AllowNulls = false, Min = 3, Max = 15)]
public string Country
{
get { return country; }
set { Set(ref country, value, () => Country); }
}
}
Getting big: Employee
Now things get interesting, Employee it’s one of the biggest tables on Northwind and has some new aspects:
- An Address field, of type AddressDN, that contains the fields of our new EmbeddedEntity.
- An MList
that will create the relational table. - A relationship to itself to represent the Employee hierarchy.
- A bunch of new value types like DateTime, DateTime? (nullable), byte[] for the photo, and a infinite length string (notes).
We should have the basis of the entity written in a few seconds with the following key strokes:
entity [Tab] [Tab] Employee [Enter] fieldString [Tab] [Tab] lastName [Tab] LastName[Enter] fieldString [Tab] [Tab] firstName [Tab] FirstNaame [Enter] fieldString [Tab] [Tab] title [Tab] Title[Enter] fieldString [Tab] [Tab] titleOfCourtesy [Tab] TitleOfCourtesy [Enter] field [Tab] [Tab] DateTime? [Tab] birthDate [Tab] BirthDate [Enter] field [Tab] [Tab] DateTime? [Tab] hireDate [Tab] HireDate [Enter] field [Tab] [Tab] AddressDN [Tab] address [Tab] Address [Enter] fieldString [Tab] [Tab] homePhone [Tab] HomePhone [Enter] fieldString [Tab] [Tab] extension [Tab] Extension [Enter] field [Tab] [Tab] byte[] [Tab] photo [Tab] Photo [Enter] fieldString [Tab] [Tab] notes [Tab] Notes [Enter] field [Tab] [Tab] Lite<EmployeeDN> [Tab] reportsTo [Tab] ReportsTo [Enter] fieldString [Tab] [Tab] photoPath [Tab] PhotoPath [Enter] field [Tab] [Tab] MList<TerritoryDN> [Tab] territories [Tab] Territories [Enter]
The class
This time inheriting from Entity is all right.
Let’s manually set the size of all the string fields, and relax nullability when necessary by removing NotNullable over the field and set AllowNulls = true on the validator.
DateTime fields
Not that for DateTime fields we just make the field type nullable when is not mandatory.
Also, we could place a convenient [DateTimePrecissionValidator(DateTimePrecision.Minutes)] that simplifies constraining our dates avoiding rounding errors. Notice that all the ValidatorAttributes, by convention, accept null values and in order to prevent null values you will need a [NotNullValidator] as well.
NVarChar(MAX) fields
We could override the field ‘note’ to have an NText type with the attribute
SqlDbType(SqlDbType=SqlDbType.NText)
But since NText is already deprecated in favor of NVarChar(MAX), we will place this attribute instead:
SqlDbType(Size = int.MaxValue)
Other string fields, like homePhone and extension, give us the opportunity to use one
VarBinary(MAX) fields
The same is applicable to ‘photo’ field. By default byte[] fields are translated to VarBinary. Instead of using SqlDbType.Image, we will use Size = int.MaxValue to make it VarBinary(MAX).
EmbeddedEntity fields
The address field, of type AddressDN, will include all the corresponding columns in the form Address_Address, Address_City, Address_Region,....
Also in order to express that the address entity itself is null (not some of the internal fields), a new Address_HasValue field will be created and the types of the internal fields will be overridden to support null values.
We can disable this feature just by placing [NotNullable] over the ‘address’ field, but in this case this is all right.
Lite fields
Lite<T> is a generic class that creates a lightweight version of an entity. It only contains Type, Id and ToStr fields.
Lite<T> can be used in your entity model to control lazy retrieving of entities and it will have no difference in the schema.
Also Lite<T> can be used in your business logic to pass it as a parameter, in your queries, or in the user interface, to populate a combo box for example. We will see Lite<T> many times in the course of this tutorial.
In this case, by making ‘reportsTo’ a field of type Lite<EmployeeDN> we stop the engine from retrieving every employee all the way up in the chain of command.
MList<TerritoryDN> fields
Finally, the field ‘territories’ of type MList<TerritoryDN> won’t create any column. Instead it will create a Table with name EmployeeDNTerritories that will look quite similar to the original one.
Note that MList are not only used to create relational tables (collection of other entities) but can also be used to create collection of values or collections of embedded entities.
Getting fast: Rest of the entities
After writing Employee entity, writing the rest of the entities should be straightforward.
Maybe it gets a little boring, but this is only for teaching purposes. In a real application you will create the entities instead of the tables, not after.
We resist making a tool that generates the entities from a legacy database automatically. Signum Framework is quite strict with some conventions and would be hard to consider any random legacy database. Also, writing the entities by hand is a good opportunity to reconsider de design and fix legacy mistakes.
Some small notes:
- Shipper (straightforward)
- Customer
- Use our AddressDN embedded entity.
- Skip Customers demographics since the table is empty and adds no value (it would be just an MList of CustomerDemographicsDN)
- Supplier
- Use our AddressDN EmbeddedEntity.
- Use URLValidators on HomePage.
- Use TelephoneValidator on Phone and Fax.
- Product
- o Make the relationship to CategoryDN and SupplierDN, both a Lite<T> relationship.
- Category
- User a byte[] field (with SqlDbType(Size=int.MaxValue)) for picture.
- Order
- Use our AddressDN EmbeddedEntity
- Make the relationship to Shipper and Customer a Lite
relationship
Finally, the only tricky point in Order entity is how to implement OrderDetails. It’s a relational table but has some information attached to the relationship (UnitPrice, Quantity, Discount).
In order to implement it, we will have to create an OrderDetailDN EmbeddedEntity:
entity [Tab] [Tab] OrderDetail [Enter] field [Tab] [Tab] Lite<ProductDN> [Tab] product [Tab] Product [Enter] field [Tab] [Tab] decimal [Tab] unitPrice [Tab] UnitPrice [Enter] field [Tab] [Tab] int [Tab] quantity [Tab] Quantity [Enter] field [Tab] [Tab] float [Tab] discount [Tab] Discount[Enter]
The result should be like this after adding a ValidationAttribute and changing the base type.
[Serializable]
public class OrderDetailsDN : EmbeddedEntity
{
Lite<ProductDN><productdn> product;
[NotNullValidator]
public Lite<ProductDN> Product
{
get { return product; }
set { Set(ref product, value, () => Product); }
}
decimal unitPrice;
public decimal UnitPrice
{
get { return unitPrice; }
set { Set(ref unitPrice, value, () => UnitPrice); }
}
int quantity;
public int Quantity
{
get { return quantity; }
set { Set(ref quantity, value, () => Quantity); }
}
float discount;
public float Discount
{
get { return discount; }
set { Set(ref discount, value, () => Discount); }
}
}
</productdn>
PropertyValidation
Let’s push the validation system a little bit. Suppose that we want to be sure that discount is something like 5%, 10%... 25%, always a multiple of 5%.
We don’t have a Validator attribute that fits these requirements, but we could create one just by creating a class that inherits from ValidationAttribute.
In this case, however, we will just override PropertyValidation method in the entity itself:
protected override string PropertyValidation(PropertyInfo pi)
{
if (pi.Is(() => Discount))
{
if ((discount * 100) % 5 != 0)
return "Discount should be multiple of 5%";
}
return base.PropertyValidation(pi);
}
This method will be called for every property of the entity, and if it returns and string, the property value will be considered wrong. If everything is ok it should return null.
This technique has the advantage that we can take into account more than one property value to make our validation logic. In this case we will need to use Notify(()=>OtherProperty) to force the re-evaluation of the validation logic for the affected properties after changing the value.
Then, just by creating a field MList
MList<OrderDetailsDN> details;
public MList<OrderDetailsDN> Details
{
get { return details; }
set { Set(ref details, value, () => Details); }
}
At this moment, Southwind entities should be able to produce a database quite similar to Northwind, let’s try:
Southwind.Logic
Reload the project Southwind.Logic. This project contains the business logic that will run on the server and will be used by the Web interface, the Windows interface through a WCF service, the Load application and the Unit Tests.
We will get into this topic more deep in the next tutorial, for now let’s start simple.
In order to create the database we first have to tell the engine witch entities will get into the schema.
Let’s just rename the example class MyEntityLogic to OrdersLogic, and change the code that includes MyEntityDN to include OrderDN instead.
The rest of the entities get automatically included by walking the dependencies of OrderDN.
Southwind.Load
Next step is reloading Southwind.Load. In this project we have already created a simple Console Application that we can use for manipulating the schema, loading data, or any other administration tasks.
The template already has a menu that allows us to create and synchronize the database. Let’s just go to SQL Management Studio, connect to localhost, and create a new database.
By convention the name of the database should be the same than the project, in this case ‘Southwind’, but you can change it in the connection string.
Once created, just mark Southwind.Load as startup project and run. Choose the first option, “New Database” by pressing “N” and… voilà! The schema get’s created according to the entities and should look like this:

Summary
In this tutorial we have seen how to create entities using a few simple primitives like IdentifiableEntity, EmbeddedEntity, or using MList<T> and Lite<T> and adding fields properties and validation rules.
Signum Framework is designed top-down to promote a code-first approach, and trying to make it work on a legacy database is a pain due to some strict conventions (like having Id and ToStr in every entity).
Nevertheless, we have seen how the generated schema is simple and predictable and can be exploited by third-party tools easily.
In the next tutorial we will get deep into how to write the business logic, load legacy data and create the user interfaces, and how these conventions will simplify our code on the long run.