Internal code in EF Core 1.1

There is very little code in EF Core that is truely “internal”. Instead, code that would traditionally have been internal has been made public but documented as internal. This post looks at what this means for application developers and how you can use this code responsibly.

History

When I started work on the Entity Framework team the prevailing philosophy was to make all code internal unless it was specifically part of the fixed-in-stone public API surface. Similarly, many classes were sealed, abstract base classes were preferred over interfaces, and methods were not made virtual. All of this was to ensure the most freedom for future development of the codebase without making “breaking changes”. Not making breaking changes was important for code that shipped as part of a monolithic .NET Framework, especially when that framework was updated in-place.

Where we are now

Skip forward a few years to a place where code is shipped on NuGet and applications control which package versions to use and when to update to a new package. Not making breaking changes is still important, but there is now some freedom to break for the long term good of the product. However, putting aside minor breaks to public APIs, there is still a lot of code that we know will need to break as the product evolves. For example:

  • The low-level guts of the implementation
  • Features that are not fully yet fully baked even though they are used internally

This is the type of code that would have been historically made internal.

Why use this code?

There are situations where applications need access to this kind of code. For example, imagine there is a bug in some low-level internal service. You can file a bug on GitHub and even send a pull request with a fix. But there will still be some period of time before that fix makes it to a production release. What if, while you waited, you could implement a fix yourself and have it used by your app without having to re-build EF or do anything gnarly?

As another example, think back to the days of Code First conventions in EF 4.1. The conventions API was not fully baked, so even though it was used internally, it was not exposed publicly. This made it very hard to implement your own conventions or tweak the ones shipped with EF. Eventing is a bit like this in EF Core 1.1–there are some internal hooks, but no baked public surface.

The solution

The solution to these problems is to make all the EF Core code public. This means that you can, for example, extend from an internal service base class and implement a fix, then use the ReplaceService API to use the fixed service in your app. Likewise, for eventing, if you want to be notified when the state of an entity changes, you can register listeners with some internal services to do this.

The consequence

But here’s the kicker. In order to move the codebase forward we still need to be able to change the low-level guts of EF, and improve the not-yet-baked APIs. Therefore, if your app makes use of this “internal” code, then it may break when you update to a new version of EF.

Usually these breaks should be minor–for example, a new parameter added to a method or a new member added to an internal service interface. Our goal is not to make it hard to upgrade to a new version, but rather to balance a few breaks when upgrading with an “internal” codebase that can evolve the way it needs to.

Drinking internal code responsibly

The first thing you need to know is when you are using internal code. Internal code is almost always in an internal namespace. For example, Microsoft.EntityFrameworkCore.Internal. In addition, all internal code is documented like this:

/// <summary>
///     This API supports the Entity Framework Core infrastructure and is not intended to be used
///     directly from your code. This API may change or be removed in future releases.
/// </summary>

So once you know that the code is internal you can make a conscious choice to use that code and accept that when you update to a new version of EF, then you might have to make some updates to your code.

Let the EF team know if you like this…

There has been a fair amount of pressure internally in taking this approach. It comes with a big risk that customers will make use of internal code, possibly without realizing it, and will then complain loudly when their application breaks. It won’t take much of this to trigger a reversal of the decision to make all code public. This could lead to all the code currently documented as internal being made truly internal. So if you think keeping this code public is a good idea, then it’s probably worth letting the EF team know this. I am happy to make sure any comments made on this blog are seen by the team.

Advertisements

7 comments on “Internal code in EF Core 1.1

  1. matra774 says:

    As KC and the Sunshine Band would put it: That’s the way (uh-huh uh-huh) we like it

  2. Joakim Olsson says:

    I think it’s a great approach. Leaves more responsibility to the programmer but also gives more flexibility.

  3. stofte says:

    My first time finding these classes, it was a pleasant surprise to see them public because my experience with classic .NET has been the exact opposite. Obviously the internal namespace enables use cases that EF does not support yet (like in-memory db schema generation/reveng), it saved me the pains of even trying out the reflection sledgehammer like many times before.

    Making them internal also seems to go against the whole .NET Core spirit of “have it your way”. EF is something I’m making use of, I should be allowed to blow it (and maybe my database too) to smithereens if I want to.

  4. Meir Blachman says:

    Are there plans to add real documentation for the ‘internal’ classes and methods?

    • @Meir Nope. Good API documentation takes significant resources, both in terms of initial investment and maintenance. For public API that is being consumed by developers who don’t know the internals this investment pays off. For internal APIs we don’t believe that it does.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s