Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DbContext.Set<T> throws exception with base class as generic type definition #6013

Closed
razzemans opened this issue Jul 7, 2016 · 4 comments
Closed

Comments

@razzemans
Copy link

We have a model definition that, simplified, looks like this:

public abstract class Item

public class ConcreteA : Item

public class ConcreteB : Item

We map these classes to their own table:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  // ...
  foreach (Type type in itemTypes) // contains ConcreteA and ConcreteB
    modelBuilder.Entity(type).ToTable(type.Name);
}

Which in the database gives us the tables ConcreteA and ConcreteB.

Consider the following method:

public Task<T> SaveAsync<T>(T t) where T : Item
{
  if(db.Set<T>().Any())
    // ..
}

Calling this method the following way:

Item item = new ConcreteA();
await SaveAsync(item);

results in db.Set<T> throwing an InvalidOperationException

Cannot create a DbSet for 'Item' because this type is not included in the model for the context.

I understand why this is happening. Nonetheless I think this is a common use case that should be supported. A possible solution might be a non-generic overload Set(Type type) so we could do:

db.Set(typeof(t)).Any()

which would be able to map to the correct table. There are non-generic method overloads for Add Attach Entry etcetera so I can't see why this would not be supported for Set.

Further technical details

EF Core version: 1.0.0
Operating system: Windows 10
Visual Studio version: 2015 Update 3

@soycabanillas
Copy link

Possibly related:
#5813
#6001

@rowanmiller, I think all of them are related to inheritance restrictions on the model context.
It's nice that the DbContext enforces some restrictions, but been able to overcome these restrictions should be possible when you know (or think so) what you are doing.

@ajcvickers
Copy link
Member

Note for triage: This is an interesting case where having non-generic Set might be useful. We should consider this and #5998 together.

@ajcvickers
Copy link
Member

Never mind. It doesn't really help because once you get the non-generic IQueryable you can't call Any (or anything else useful) on it without treating it as a generic and doing manual reflection calls or expression building.

var setMethod = typeof(DbContext).GetMethod(nameof(DbContext.Set)).MakeGenericMethod(t.getType());
var query = (IQueryable)setMethod.Invoke(db, null);
var results = query... // What to do here? No ToList, no Any, etc.

@rowanmiller
Copy link
Contributor

Agreed, because of how LINQ works the only option is to use MakeGenericMethod to create a DbSet<T> based on the type being used.

@ajcvickers ajcvickers reopened this Oct 16, 2022
@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Oct 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants