Update on Computed Properties


A while back I wrote a post that introduced the concept of Computed Properties. Since that time we’ve had a number of conversations with both customers and internal partners and we’ve had some new ideas, that have changed our thinking somewhat. 



  • First off we decided to implement Model Defined Functions, which are significantly more powerful and flexible than Computed Properties, and provide overlapping capabilities.

  • Computed Properties on the other hand, would never have been structurally part of the entity, which lead to some tough choices and probable customer confusion:


    • Do you always pay the cost of materializing the Computed Property even when it is not required?

    • What about if there are lots of Computed Properties on the Entity?

    • Today in order to materialize an Entity and it’s properties, computed or otherwise, the Entity Framework needs access to setters. Unfortunately the existence of the Setter, sends an erroneous message that Computed Properties can be altered and persisted.

    • Upon further investigation we discovered that Computed Properties didn’t actually address the requirements of Reporting Services, which was one of the original drivers for Computed Properties. Our original design called for computed properties to operate over an instance of an Entity, and it turned out that Reporting Services needed computed properties to operate over both an instance and a set of instances. Model Defined Functions on the other hand are flexible enough to handle both of these scenarios.

  • In the future it may be possible to gain all the benefits of computed properties without any of the above issues, by extending our integration of Model Defined Functions with LINQ so that the [EdmFunction] attribute can be applied to CLR properties too.

    If we did this the first parameter of the specified Model Defined Functions could be mapped to be the CLR type containing the property itself.  This would allow a Computed Property, backed by a Model Defined Function, to be used in a targeted way in LINQ queries, without any of the illusions that this might somehow be set-able or structurally part of the entity.

Given all these points we started to think Computed Properties just weren’t as important.


We think our best course of actions in the short term is 1) to focus on supporting Model Defined Functions and 2) ask for your feedback on the relative importance of Computed Properties given the points listed above.


So what do you think?


Do Model Defined Functions address most of the scenarios for Computed Properties?


Particularly if in the future we can treat CLR properties as stubs for Model Defined Functions?


As always we are very keen to hear what you think.


Alex James
Program Manager
Microsoft


This post is part of the transparent design exercise in the Entity Framework Team. To understand how it works and how your feedback will be used please look at this post.

NB:
For more background on the origins of [EdmFunction] check out this post.

Comments (11)

  1. Kristofer says:

    My 0.7 baht (== ~2 cent):

    "<i>Do you always pay the cost of materializing the Computed Property even when it is not required?</i>"

    No. Only materialize when called for, otherwise it is not a property or function; always materialized==fields. Always materializing would make computed properties and MDFs banned in many dev shops. (something that _always_ result in [hidden] overhead is a really good way to shoot oneself in the foot)

    Even for non-computed members I think you need to re-think how entities are populated today [in EFv1]. Partially populated entities (without needing a new ‘partial’ entity definition in the CSDL) is something desperately needed. (northwind example: employee details without photo)

    "<i>CLR properties as stubs for Model Defined Functions</i>"

    No. At least not without a way to flag it as ‘not part of the model’, e.g. a "[NotInModel()]" or "[EFIgnore()]" attribute.

    I think MDFs should be exposed as regular functions, not property gets. CLR properties on entities should be allowed _without_ anything under it in the model.

    MDFs would already cover 99.5% of the usage scenarios I can imagine for computed properties. 100% if "reverse computation"/"property set" is not supported. That said, computed properties with reverse breakdown/"property set" definitions would be neat. E.g. person name parts <-> person full name.

  2. efdesign says:

    Kristofer,

    Partial loading as you call it is definitely something we have been considering (i.e. the don’t load the big blob unless I really need it scenario). It isn’t looking likely in .NET 4.0 though.

    CLR Properties without anything under them in the model are already supported. The caveat of course is the value isn’t persisted and it can’t be used in a LINQ Query. So I think this is a somewhat orthogonal idea.

    Note: not adding the [EdmFunction] attribute to the CLR property would be the equivalent of adding your [NotInModel()] attribute.

    So I see little point in the [NotInModel()] attribute, essentially it is the default state of a Property that has no corresponding Property in the EntityType.

    Cheers

    Alex

  3. Kristofer says:

    ‘Partial loading’ should be really high up on the feature list IMO – it is very important from a performance perspective…

    Ok, my bad re the attributes. I assumed that "CLR properties as stubs for Model Defined Functions" meant that CLR properties with no mapping would [by default] attempt to find/call a matching function.

    Either way, separating properties and functions in the model so they map to properties and functions in the generated classes is probably a good idea. Very little overhead implementation-wise but allows users the flexibility to choose which one to use.

    And as I mentioned – for properties, an optional definition for ‘setter’ logic (again defined in ESQL, RegExp, or a method call to an assembly or webservice) would open up a bunch of possibilities:

    <Property Name="FullName" Type="String" Nullable="false" MaxLength="30" Unicode="true" FixedLength="false" Computed="true" Ordinal="4">

       <DefiningExpression Type="Get" Language="ESQL">FirstName + ‘ ‘ + LastName</DefiningExpression>

       <DefiningExpression Type="Set" Language="RegExp">^(?<Title>[ ][A-Z]+)*(?<FirstName>[A-Z]+)(?<MiddleName>([ ][A-Z]+)?)[ ](?<LastName>([A-Z]+[ ])*([A-Z]+))$</DefiningExpression>

    </Property>

    …or the appropriate extensibility interfaces allowing third-party implementations of the same. 🙂

    T4 for code generation goes a long way towards the latter, but some additional extensibility points in the visual designer to complement that would be neat; allowing third-party extensions/add-ins to add new properties [mapped to their own ‘structural annotation’ members] in the designer etc

  4. shawn says:

    I think having some way to define Computed Properties, either directly or backed by Model Defined Functions, is critical for being able to fully express entities in an entity/object-oriented way.  It allows you to define and query data as part of the entity/model itself.  Often times this is the preferable way for computed data to be consumed.  It certainly is in our scenarios.  This is one of the features we are most excited about.

  5. Pedro says:

    Sorry to go a little of topic here, but I was wondering if I could download a preview version of EF v2 just to play with it.

    Thanks.

  6. simmdan says:

    EF v2 preview is not available yet.  We’re working on that and will make something available as soon as we reasonably can.

    – Danny

  7. Pedro Brown says:

    Thank you for your answer Danny.

    I have to say that I’m really excited about what is beeing done in the EF. What I want to know is: Can we make suggestions to make EF more a MDD framework, or it’s purpose is just to be an O/R M and leave the MDD area to Oslo?

    Thanks.

  8. Pedro Brown says:

    Sorry, MDD is (Model Driven Desing), but I think that what you guys use is DDD (Domain Driven Desing).

    Thanks again.

  9. Ike says:

    One great benefit of computed properties would be to add non-model data to entites being delivered via REST (ADO.NET Data Services).  Interjecting "computed" data into my entites has become absolutely necessary and since I…

    – can’t do that with EF (computed properties would be nice?) so ADO.NET Data Services is out

    – can’t return a JSON-serialized object that includes a EF entity item from a WCF operation if that EF entity includes a reference to another EF entity (known issue…very specific error occurs if you try to do that)

    …I have had to resort to creating separate contract types for each EF entity type I want to return as JSON.

    If EF allowed me to add computed properties, I could scrap most of my contract types.

  10. Yann says:

    In Nhibernate I use the formula (computed properties) a lot.

    I need it to nicely handle localisation (multi language). The way i do it is that i set a formula for each property i need to translate. This formula will lookup for the property in a "Locale" table filtering on the current language (using nhibernate filter).

    Exemple :

    public class TransactionType

    {

     public int Id { get; set; }

     public string Label { get; set;}

    }

    public class TransactionTypeLocale

    {

    public int TransactionTypeId { get; set; }

    public int LanguageId { get; set; }

    public string Label { get; set; }

    }

    in my mapping I set mapping.Map(c => c.Label).Formula("COALESCE((SELECT l.label from transaction_type_locale l where l.transaction_type_id=id and language_id=:LanguageFilter.LanguageId), label)").Length(255);

    This way it's totally transparent in my application and if there is no translation for the current language i can fallback on the default value of the row.

    Of course i'm not doing this for each property by hand, it is handle by the automapping that generate the formula when needed.

    It would be great if EF could support this scenario, it's the only thing that stop me from using it !

  11. Paul says:

    I think not being able to specify computed properties on the entities themselves is restrictive and lacks the elegance you would get when defining a traditional business object.  This forces the developer to then translate the entities into objects that do support this (more work), or requires that you define a model-defined function that is effectively global rather than scoped to the entity (not elegant, and seems a bit 'old school').

    You can of course define an extension method and mark with attribute to provide a more natural syntax, and even put in CLR code that duplicates the MDF so that you can call both direct and via query.

    However, one extra step would 'solve' this (though I suspect there are 'issues?!'), and that would be to allow us to define a property in the entity class, and mark with a suitable attribute that then takes the 'this' as the parameter to pass to the function.

Skip to main content