What's the difference between Signum Framework and other frameworks (Linq to Sql, Entity Framework)?¶
In Signum Framework you start writing the entities in C#, then the database is generated from them, not the other way around. Just like what Django
for Python does. This difference has a lot of implications, the most obvious one: You need a new database. But there are also a lot of good ones :)
- There's less code duplication since your entity model is the only authority.
- All your code is C# code, so refactoring works fine.
- You can place validation straight on your entities using attributes. This is not possible using partial classes.
And more importantly, having some basic features in every single entity makes it way more simple to write generic code to deal with the entities on every layer, UI, BL, and DB. This makes things like EntityControls
Is there POCO support?
POCO stands for Plain Old C# Object. An ORM with POCO support is one that can deal with classes that have no previous knowledge of the ORM. This is called Persistence Ignorance. It's explained here
We know that POCO is a feature required by a lot of people 'disappointed' with the current LINQ Providers (no with LINQ as a language extension). Unfortunately POCO works badly with any other aspect of an ORM. For example, in order to avoid DataContext and make SOAP Serialization possible in a simple way, we embed change tracking
inside of the entities. Our entities also have integrated support for validation
But what's more important, Signum Framework imposes that every single IdentifiableEntity
) needs and Id and a ToStr field. These fields also create columns in the database. So it's not only that Signum Framework imposes your classes to inherit from some certain base classes, it also imposes your tables to do it. That's why you need a new Database. In that sense Signum Framework has a lesser support to POCO than most of the frameworks.
These requirements, however, pay for themselves because they enable huge levels of code re-utilization. Think of it like having System.Object in the database: Thanks to having ToString and GetHashCode on every single object you can add them to a List, a Dictionary, ComboBox.... We can do the same but on every single layer of the application. Thanks to having a solid foundation for our entities we can use Lite<T>
to solve traditional problems like lite loading and user interface without code behind in a neat and powerful way.
These basic requirements also enable the integration of application modules. The most important feature of Signum Framework.
How does serialization work?
The entities are marked with SerializableAttribute, and the change tracking is embedded, so they can be sent using old legacy Soap/Binary serialization.
We don't use DataContractsSerialization in the service that communicates with the client application
, so these services are not 'SOA'. We use NetDataContractSerialization instead. That's why we can send full graphs
full graphs to the client application, and we have change tracking and validation in there as well. Also, we don't have to decorate the entities with DataContract.
How does Signum Framework support inheritance?
We support only Table-per-class and polymorphic foreign keys because it's the only model that allows module integration and refecentes to 'everything' (ImplementedByAll). You can know more here
. Inheritance is also integrated in LINQ queries using normal C# casting.
Is it possible to modify the DB Schema?
There's a per-connection data structure, Schema
, that contains all the names of the tables, fields, etc... This is the ONLY source of information that the framework uses to deal with the database (create tables, save retrieve objects, linq queries...). You can customize the 'cosmetics' of the database in many different ways, but the truth is that the Framework imposes the ultimate structure of your schema in order to reduce mismatch between your entities and the tables.
Is there support for complex types?
As long as you model the entities using Base Entities
you can do what you want. You can also uses EmbeddedEntity
to embed all the fields of an entity in his parent.
Is there support for Many-to-Many relationships?
By using MList
you can easily make many to many relationships.
The primitives defined in Signum.Entities can be combined in many ways. Nested EmbeddedEntities, Lites, MList of Lites, MList of values, MList of Entities, MList of EmbeddedEntities... there are a few forbidden ones however, like nested MList, or MList inside of an EmbeddedEntity.
How are relationships handled? ¶
A field of any Entity type is mapped as a FK to the Id column of this entity type (they allways have ID). You can also use polymorphic-FKs
(ImplementedBy and ImplementedByAll). Lite
has no difference, since it is just a runtime behavior.
Is there support for Stored Procedures?
Nope. You can write your own stored procedures if you want, but there's no framework support.
Saving and retrieving general entity graphs, and LINQ queries, is quite 'non-deterministic' about the SQL that will be generated, so Store Procedures are not an option.
Also, our aim is to encourage writing everything in C#, so refactoring is faster and your application evolves quickly. It also simplifies module integration.
We are planing to support Batch Update and Delete
How is laziness supported in the relationships?
Signum Framework's approach to liteness loading controls is both Explicit and Structural:
- Explicit because it depends on you to determine if the entity is going to be retrieved or not (not transparent).
- Structural because its defined in your entities relationships, not in the operations over them.
is the class that is used to indicate that a relationship is lite. This solution has two nice consequences:
- Lazyness is part of an entity interface, so your business logic breaks at compile time and forces you to deal with it. (EntityControls however, know how to solve the situation)
- This model allows sending entity graphs to the client application, where the DB is not available.
Is there some kind of concurrency support?
The basic entity, IdentifiableEntity
has no concurrency support. Entity
has a Ticks field that is checked on any update. (Just like Linq to SQL). Explained in the diagram in here
Also, we recommend using Shapshot Isolation
in your connection
. It's not enabled by default because it requires setting a flag on in the database.
Is there support to save complex graphs of entities?
Absolutely. You can save London Tube
as a list of TubeStationDN entities related to each other at once if you want.
How are transactions handled? ¶
We use Transaction
class, a TransactionScope-like class that allows a clean syntax to deal with transactions.
When Transactions are nested, the nested ones become silent, instead of promoting a distributed transaction. This makes your business logic easier to compose.
How is object identity preserved in memory? ObjectCache
class allows many DB Operations to use the same entity instances when the same DB entity (type and id) is required. Again, it's an explicit solution, not a transparent one.