Design Meeting Notes - March 21, 2013

Missing property handling in lightweight conventions

Currently lightweight conventions get applied to any property that matches a given name (when a property name is used) for which the configuration is applicable. If the property name does not match or the specified configuration cannot be applied, then the configuration is ignored. For example, if your entities have keys named “Key” then this lightweight convention will do nothing because no property named “key” is found:

modelBuilder.Entities()
    .Configure(c => c.HasKey("key"));

Similarly, assuming FirstName is a string property, then this will do nothing because strings cannot have precision:

modelBuilder.Entities()
    .Configure(c => c.Property("FirstName").HasPrecision(10, 2))

And this will never do anything because no string property can ever have precision:

modelBuilder.Properties<string>()
    .Configure(c => c.HasPrecision(10, 2))

This behavior can be nice because it removes the need to select/filter on the entities/properties to which the configuration will be applied. However, it also seems unintuitive in terms of the mental model for how conventions and configuration works. This in turn leads to situations where the expectation is that if the configuration is wrong, then it should throw, but because it doesn’t, then it must be right. In other words, a developer might spend a lot of time trying to figure out what is wrong with the application without realizing that their configuration is being silently ignored.

Therefore, we will change lightweight conventions to throw in situations where a property with the given name cannot be found or where the specified configuration is invalid. This means that conventions may need to use Where/Having or constrain by type in cases where it was not required previously. However, this results in a clearer mental model with better error reporting when a mistake is made. (See CodePlex 941.)

Code First stored procedure mapping

These items are specifically about modification function mappings—i.e. insert, update, and delete procedures.

TPH mapping

TPH function mapping expects a single function per type, which can seem a little strange since all types map into a single table. It would be good to be able to map all types to a single procedure. EDM doesn’t really support this right now and it would be a big change to make it work, so we won’t be doing anything for EF6. It is possible to get some of the way there using optional parameters, but the discriminator is never passed to the stored procedure which makes even this hard to do.

Configuration by conventions

It is currently not possible to configure stored procedures using lightweight conventions. Given that the current plan for lightweight conventions is to bring them up to parity with with traditional configuration conventions it may be possible to do this once the conventions work has been done. (See CodePlex 935)

Many-to-many naming

The non-deterministic join-table naming issue can cause problems—see CodePlex 816. Beyond this, the stored procedure naming convention is somewhat strange (see CodePlex 976):

Given a model with this structure:

Person
{
    List<Animal> Mounts;
}

Animal
{ 
    List<Person> Riders;
}

A table like this is created:

PersonAnimals (
    Person_Id, 
    Animal_Id)

And the insert function is mapped like this:

Person_Mounts_Insert(Person_Id, Animal_Id)

(Or configured from the other direction:)

Animal_Riders_Insert(Animal_Id, Person_Id)

This will be fixed to use just type names with no pluralization in the stored-proc name. For example:

PersonAnimal_Insert(Person_Id, Animal_Id)

This is consistent with non-many-to-many tables.

Out parameters for result bindings

It would be good to allow result binding to be done without output parameters. However, this would require significant changes to stored procedure mapping in core EDM and so does not fit for EF6. Tracked for the future with CodePlex 975.

Last edited Mar 21, 2013 at 9:58 PM by ajcvickers, version 2