LA.NET [EN]

EFArchive

May 12

After hearing lots of good things about EF 4.1 and its new code first approach, I’ve decided to take a look to see if it’s as good as they say. I must admit: the latest version has lots of good things, but it still is far far away from my favorite ORM (which, btw, is NHibernate). To test the code first approach, I’ve tried to build a simple model which reproduces most of the features I tend to use in day-to-day database persistence operations. This isn’t a real case example, but it’s close enough for seeing if it does what I want:

public class Address:ValueObject {
    private Address() {
        Street = Municipality = "";
    }
    public Address( string rua, string localidade ) {
        Street = rua;
        Municipality = localidade;
    }

    public String Street { get; private set; }
    public String Municipality { get; private set; }
}

public enum EntityKind {
    Individual,
    Coletiva
}
    public enum ContactKind {
    Phone,
    Email
}

public class Contact:ValueObject {
    public String Valor { get; private set; }
    public ContactKind ContactKind { get; private set; }

    public Contact( string valor, ContactKind contactKind ) {
        Valor = valor;
        ContactKind = contactKind;
    }

    private Contact() {
        Valor = "";
        ContactKind = ContactKind.Phone;
    }
}
public abstract class Entity:EntityWithAction {
    public String Name { get; set; }
    public Address Address { get; set; }
    public DomainAction Action { get; set; }
    public abstract EntityKind EntityKind { get; }

    private IList<Contact> _contacts = new List<Contact>();
    public IEnumerable<Contact> Contactos {
        get{ return new ReadOnlyCollection<Contact>( _contacts );}
        set { _contacts = new List<Contact>(value); }
    }
    public void AddContact(Contact contact) {
        _contacts.Add( contact );
    }
    public void RemoveContact(Contact contact) {
        _contacts.Remove( contact );
    }
}

public class Individual:Entity {
    public override EntityKind EntityKind {
        get { return EntityKind.Individual; }
    }
}
public class Company:Entity {
    public override EntityKind EntityKind {
        get { return EntityKind.Coletiva; }
    }
}

So, what do we have here:

  • we’ve got inheritance: just for the kicks, I want to have two different kinds of entity and they should be saved in the same table.
  • we’ve got components (I believe they’re called complex types in EF). Notice that Address is a component and Entity has a collection of components (Contacts).
  • I don’t want to allow direct access to  thecontact collection to anyone consuming my domain. All additions and removals should go through the Add/Remove methods.
  • I want to preserve my domain object’s behavior. I’ve got entities (ex.: Individual) and value objects (ex.: Address) with quite distinct behaviors. Notice also those ValueObject and EntityWithAction base classes… They’re inspired in the fantastic S#arch classes (whose use I recommend) and solve several interesting problems (like equality and hash computation) for entities and value objects.

After a morning trying to make my mappings work, I’ve simply quit. Here are some things which really bother me:

  • EF doesn’t seem to support collection of components. With NH, I can simply say that updating an entity should always delete and insert its contacts on a related table. Is this doable in EF? Because this kind of behavior shouldn’t require any back pointer in my Contact object…
  • EF requires the use of ICollection interface for associated entities. This isn’t really compatible with a real domain model where I do need to control what is done over an instance of an object.
  • There still isn’t enum support.
  • The fluent API for registering isn’t really that fluent. Worst: it has overloads of methods which return different types (yes, the CLR does support those overloads, but the C# will only allow it for different parameter lists). This leads to frustration really quickly. For instance, I’ve spent several minutes trying to define the discriminator column only to find out that the Require overloads return different results…which don’t “flow”…really…
  • I really didn’t get far enough to see if I could define the mapping at the field level, but I’m assuming that isn’t possible.

Probably these problems can be easily solved…probably not. I don’t know because I just gave up! Why did I gave up? Well, simply because there’s NHibernate which can do all this for me in a rather quick way, without any pain, and with very little changes in my domain model. And that’s why I’ll keep using NH for my domain and I’ll probably resort to EF for the reporting side of my apps…I’m sorry, but I think that EF is still nor ready for real domain models…

Jan 20

In these last 2 days I’ve been reading several documents on the ADO.NET Entity Framework. My main objective here is see if it is ready for being used in projects based on the DDD philosophy. Even though I still haven’t started writing code, it seems evident to me that EF is still a far away from being my persistence platform of choice. before going on, here’s what I intended to do in my current project:

  • start by building an adequate OO model to my current domain. Even though the model needs to accommodate some info that only matters to the db (ex.: Id and version fields), I would love it to be relatively PI;
  • Introduce the concept of repository and then build several implementations with different technologies in order to compare the final result;
  • keep it really simple. In fact, I kept it so simple that I’m not even using inheritance. Just plain references and collections to other entities and value objects.

With these objectives defined, I started looking at EF. After some searching, it become evident that I’d really have to change my objects (beside adding the ID and Version fields). Ok, so EF does not support POCO, but it does support something they called IPOCO. According to what I’ve seen (and I can be wrong), the idea is that instead of reusing the  EF default base class for entities, you could simply implement some interfaces (according to my research, you should be interested in implementing IEntityWithChangeTracker,IEntityWithKey and IEntityWithRelationships – of course,depending on your current scenario). btw, implementing these interface will also mean that you’ll have to change your properties’ code because you’re supposed to notify a “tracker” whenever one of the properties of your objects changes.

Besides the interfaces, you must also decorate your props/classes (and even the assembly) with some attributes. For example, you should use the EDMScalarPropertyAttribute for a primitive property that should be mapped onto a table column (not related, but isn’t this a violation of one  of the naming rules verified by FxCop? I’m glad that I’m not the only one breaking them :) ). Hum…not looking good, right?

Now, I told you that I wasn’t using inheritance and this is  a pity because it seems like EF supports all forms of inheritance available on ORM mapping. And it even looks like you can configure these options by using the designer (ok, I didn’t checked it but I’ve found at least an example of these mappings which showed how to do that in the designer). Unfortunately, it seems like for adding value type mappings (I believe that the technical term in EF is complex types) you’ll really need to write the CSDL file by hand and then use the command line tool (edmgen.exe) to generate the remaining files.

Now, this (having to do it by hand – and I’m hoping that someone will drop a comment saying that there is a way of doing this in the designer) is really bad. One of the advantages that I thought EF had was providing a good designer (something which NH doesn’t have). Even though this is v1.0, i did expect to be able to do this from the designer as I didn’t really intended to get my hands dirty with the XML (If I really need to understand all those XML dialects they’ve created then I’ll probably use that from within the VS instead of using their designer). So, in the end I guess that this is minus 2 points for EF.

My last complaint of the day is related with references to other instances. You need to use some base class for those scenarios. For instance, if your object has a collection of other objects, each mapped to different tables, then you’re supposed to model that by using an EntityCollection<T> class. Again, I don’t like this.

So, this leaves me with one option: using a translation layer for mapping the entity generated classes into my domain classes .I don’t really see much value in using the entity generated classes as my domain classes and one of my objectives was to have a fixed set of domain classes. I do hope to have better reviews after starting to write some code since my first impressions are really that good.

Now, I’ve also seen a PDC vide which looks promising but i really didn’t find any release with those beta bits, so I’ll just keep using the current version until another more promising version is released.