is the only class that you can use to model One-To-Many and Many-To-Many relationships on Signum Framework.
This class is a full featured List, with easy support for data binding and change tracking.
In the New version more List<T><esc/> methods have been included in MList, like FindIndex, FindLastIndex, LastIndexOf
Since MList<T> inherits from Modifiable
, it has to override SelfModified to know when changes have happened. It does so by remembering and testing the sum of the Hash Code of the elements. Thanks Mads Kristensen
for the idea.
So reordering items does not affect change, since ordering is not guaranteed on the database.
MList implements INotifyCollectionChanged
, so it will fire events each time an element is added, removed, etc... This is very convenient for data binding to WPF's ItemsControl
INotifyCollectionChanged is defined in WindowsBase, and is the .Net 3.0 version of IBindingList
. Unfortunately, this interface resides in WindowsBase.dll, so you will have to link this Assembly until Microsoft guys re-arrange things in .Net Framework 4.0
We have already agreed that Signum Framework is all about writing the Entities code and letting the Engine have control over the Schema. MList is not an exception here, and in some senses they are the most radical decisions about database mapping.
Usually you make a One-To-Many relationship between Country and Continent by adding a FK in Country pointing to Continent. This is Databases 101, and is what will happen if you add a ContinentDN field in CountryDN.
However, if you add in ContinentDN a field like this:
<span class="type">MList</span><<span class="type">CountryDN</span>> Countries;
then the behaviour is different, a relational table with name trtlContinentDNCountries (trtl + ClassName + FieldName) is created that looks like this:
This table has the following things:
- An Id Column: This column is not used by the Signum Framework. However, we created it because it's a good idea to have Id column on every table, and also because future versions of MList could have better knowledge of changes and change only the needed rows, instead of recreating all of them as it does in the current implementation.
- A idParent column: Contains a reference to the entity that owns the collection.
Now all the Back-references are names idParent
- The actual translation of T in the database: In this case, since CountryDN is a reference type, an FK with name idCountryDN is enough.
This last point is very important. Tables generated by MList are relational tables just in the case that T is a reference type, but it could be almost any other thing, so maybe Collection Table is a better name:
- Value: If storing Telephones just as MList<strings> in a PersonDN entity, the result will looks like this:
- EmbeddedEntity: The entities will just be embedded in the collection table. Very common pattern.
- Lazy: Just like the reference example.
- ImplementedBy and ImplementedByAll: The collection table will be the owner of the polimorphic foreign key.
- Enums: ...you get the idea, don't you?
The only think thas is not currently possible to do with MList is to create an MList of MList, since it needs an special consideration (back IDs pointing to IDs of collection tables) and we really don't see the point.
There are some rules for creating good names for fields in the SchemaBuilder
that's why Value is used in the case of <esc>MList<string> Telephones
is the foundation of Signum Framework, and promotes a functional style of code, following the Linq path and going a bit further.
MList is not an exception. There's a ToMList() extension method in Signum.Entities.MListExtensions, so remember to include the namespace.