views:

73

answers:

3

I'm building a small timing application using the MVVM pattern, using entity framework for persistence. At this stage, my logic is pretty thin, as I only need to perform a few calculations and aggregations on related data. At the moment, I have implemented these by writing them in a partial class of the entity class.

For example:

// entity framework generated
partial class Lap {
  int Id { /* boilerplate */ }
  DateTime StartTime { /* etc */ }
  DateTime EndTime { /* etc */ }
}

// in my partial class (written by me)
partial class Lap {
  TimeSpan Duration {
    get { return EndTime - StartTime; }
  }
}

Is it bad practice to drop extra logic straight onto the entity-generated classes? Should I make another domain layer for this logic?

+7  A: 

You are doing the very thing for which partial classes were designed; adding relevant logic to a code-generated class without bogging down the inheritance tree. Keep it up.

Addition:

From a page in the font of all tribal knowledge, Wikipedia (emphasis added):

The purpose of partial classes is to allow a class's definition to span across multiple files. It is especially useful for:

  • Very large classes (where it is cumbersome to navigate with an editor through a single file)
  • Separation of concerns, in a way similar to aspect-oriented programming but without using any extra tools. An example is shown below.
  • Allowing multiple developers to work on a single class at the same time without the need for later merging files in source control.
  • Allowing a separation between the class interface and the implementation-related definitions (Separate definitions of the public and private parts)
  • Easing the writing of code generators, such as visual designers. This is perhaps the most useful reason. It is a challenge to develop code generators that can manage the generated code when it is placed in the human-written code:
    • Requires a lot of parsing of unnecessary code, just to find a place to insert the generated code. Altering the code is also a problem. Poorly written generators hold the potential risk of damaging the entire file.

Using partial classes, the code generator processes a separate file, and is thus alleviated from all the above mentioned problems.

kbrimington
Here, here! +1 for that.
Lazarus
I agree entirely with this response and implement this design in many of our solutions. One thing I find useful is to try and maintain a convention for where you store your partials. We like to extract out the T4 generated POCO classes into our separate Model Assembly and then include an additional folder called Behaviours that holds all the associated partial classes. Whatever works for you, just keep it consistent.
Daz Lewis
+1  A: 

I have to admit doing this to POCOs and have found it very productive. Other common uses

  • Fullname = FirstName + " " + Surname
  • CostIncl = Excl + Tax
  • Sometimes can also aggregate totals in child entities (e.g. InvoiceTotal = Sum of all LineItem.Totals)

etc

There are some caveats

  • If you are sending these entities directly across the wire (e.g. WCF or ASMX), ensure they aren't marked as Serializable / DataMember, as they will fail serialization without a setter
  • And if you aren't (e.g. mapping them across the wire or for MVVM purposes) you will need to duplicate the effort
  • Edit : As per Stephen's comment, using a derived property in a LINQ query (which hits SQL) will fail (since it can't be mapped to SQL).
nonnb
One extra caveat: When you are defining custom properties, such as `Fullname { get { return Firstname + " " + Surname; } }` (or `Duration` in his case), please note that using this property in a LINQ query will fail at runtime.
Steven
Thanks for the heads-up Steven. Something like `averageDuration = Laps.Average(lap => lap.Duration.Milliseconds)` would also fail?Does this only apply to IQueryable queries (ie, using EF) or can it fail in linq-to-objects as well? eg `Laps.AsEnumerable().Average(lap => lap.Duration.Milliseconds)`
BleuM937
A: 

It's not bad to use the partial classes of the Entities when using the Entity Framework. However, you just need to ensure that you don't mix business logic with data access logic in the members of the partial classes. Otherwise, it's going to be hard to write unit test code without connecting to the database.

The BookLibrary sample of the WPF Application Framework (WAF) shows how a WPF MVVM application might look like when the domain layer uses EF Entities.

jbe