Entity Framework Core DbContext.RemoveRange and type constraints

c# entity-framework-core generics


This code throws an exception

System.InvalidOperationException: The entity type 'List<..>' was not found. Ensure that the entity type has been added to the model.

private static void Update<T>(DbContext context, ICollection<T> existing, ICollection<T> updated)  // where T: class

However, if you add the type constraint where T: class no exception is thrown. Why is this? I was under the impression C# type constraints didn't affect run time behavior like this. Both versions compile fine.

2/12/2019 9:44:39 PM

Accepted Answer

It's not the runtime behavior, but the compile time method overload resolution and covariance here:


RemoveRange method has two overloads:

RemoveRange(IEnumerable<object> entities)


RemoveRange(params object[] entities)

Having class constraint allows C# compiler to pick the overload with IEnumerable<object> - because ICollection<T> is IEnumerable<T>, and IEnumerable<T> for reference type T is covariant, hence is IEnumerable<object>.

Without class constraint, the only available options is the method with params object[] argument. And here comes one of the drawbacks / side effects / traps of params object[] construct - every single argument arg with type other than object[] is treated as object and passed implicitly as new object[] { arg }.

So, in the former case the actual call is


while in the later case it is

context.RemoveRange(new object[] { existing });

In other words, the list is passed as object, which leads to the runtime exception in question.

The same applies to all other Range methods of the DbContext class - AddRange, UpdateRange and AttachRange.

2/13/2019 12:07:46 AM

Related Questions


Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow