2

I'm using EF (Code first) and I'd like to isolate the properties from the methods (many of the methods reference other libraries that I don't want my database project to have to reference).

As an example, say I have this class

public class Person
{
  public string Name { get; set; }
  public void SayName()
  { 
    SomeExternalAssembly.Say(Name)
  }
}

Because SomeExternalAssembly has nothing to do with the database I'd like to move the SayName method to another assembly while maintaining it in a "version" of Person.

In my ideal world (which doesn't work and is probably a bad idea) I'd inherit Person to DerivedPerson then just cast it back to Person when I need to save it to the DB. While I can perform the cast, when I attempt to add it to the DB I get a System.InvalidOperationException: Mapping and meta data information could not be found for EntityType 'DerivedPerson'.

Since that didn't work the next best solution I can come up with is just adding a Person property to my new class:

public class PersonB
{
  public Person Data;
  public void SayName()
  { 
    SomeExternalAssembly.Say(Data.Name)
  }
}

While this would work, I'm looking for something a little cleaner (and ideally less code changes). The next thought I had was to go with inheriting then add a conversion method using reflection.

Does anyone have a better approach?

MikeH
  • 139
  • 2
  • 1
    How about `Say(name, someExternalAssembly.NameSayer)`? Or even better, `SomeExternalAssembly.SayName(anyArbitraryObjectWithAName.Name)` that accepts a mere string as input? – Robert Harvey Aug 03 '15 at 19:57
  • @RobertHarvey While those are great suggestions for the simplistic example I've given, they make less sense in the real program. – MikeH Aug 03 '15 at 20:01
  • Your example couples too closely to SomeExternalAssembly. – Robert Harvey Aug 03 '15 at 20:02
  • @RobertHarvey Yeah...I'm terrible at making simplified examples... – MikeH Aug 03 '15 at 20:07
  • @RobertHarvey Upon looking through my code a bit more, your suggestion isn't as far off as I thought it might be. I thought I had external references littered everywhere, but there are only about a dozen...few enough to refactor. – MikeH Aug 03 '15 at 20:23

1 Answers1

1

If you are 100% sure you want to "bolt on" methods onto these EF table/classes, then just open them up as partial class in a separate file and add the methods needed:

// location -> /EntityPartials/Person.cs

public partial class Person
{
  public void SayName()
  { 
    SomeExternalAssembly.Say(this.Name); 
    // 'this.*' above is optional but could be used to quickly identify EF data-properties.
  }
}

For the record, I would NOT recommend using partials like this that need to talk to external components that require any kind of class state, since you can't really control constructors easily in EF and therefor lose your power to inject dependencies. However, I have a LINQ-2-SQL project that makes lots of use of the pattern above to do various things like string formatting, conditional validation, etc.

Graham
  • 3,833
  • 1
  • 21
  • 18
  • But that doesn't really decouple the dependency on SomeExternalAssembly. – Robert Harvey Aug 03 '15 at 20:03
  • @RobertHarvey Exactly correct. – MikeH Aug 03 '15 at 20:05
  • If you had `Person` inherit from an `ISay` class and provided a new constructor that takes an `ISay` object as one of its parameters, would that make it injectable without breaking EF? – Robert Harvey Aug 03 '15 at 20:08
  • I'm not sure how you'd tell EF to use your DI-based -constructor for that Person entity when it does a general query, but I suppose its possible. – Graham Aug 03 '15 at 20:10
  • You wouldn't... You'd have to cast it to the interface to Say the name. As you can see, I haven't fully thought it out. – Robert Harvey Aug 03 '15 at 20:13