Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Casting DbSet<Entity> to its DbSet<IEntity> without pulling all entities to memory

My Problem is that the system I am working with expects Data as IQuearable<IEntity> and entityframework gives me data as IQueryable<Entity>

This is from an interface I need to implement:

public IQueryable<T> GetData<T>() where T : class, IData {}

I have a DbSet created as context.Set(MyEntityType), where MyEntityType is typeof(Entity).

I have been trying a few things by now and not sure how I will get around this. (its all auto generated code from codedom, but made a test below to see that it can work, but havent got things working)

I made a wrapper for testing and the problem is here LINQ to Entities only supports casting EDM primitive or enumeration types If I can make this work I can make my other parts work also.

public class DbSetWrapper<C1Data,Entity>
    where C1Data : IData 
    where Entity: class
{

    public DbSetWrapper(C1AzureStoreRPContext context)
    {
        Data = context.Set<Entity>().Cast<C1Data>();
    }
    public IQueryable<C1Data> Data { get; private set; }
}

public class C1AzureStoreRPContext : DbContext
{
    static C1AzureStoreRPContext()
    {
        Database.SetInitializer<C1AzureStoreRPContext>(null);
    }
    // Methods
    public C1AzureStoreRPContext(string connectionstring)
        : base(connectionstring)
    {

    }

    // Properties

    public DbSet<AzureStoreSubscriptionWrapper> AzureStoreSubscriptions { get; set; }
}
 public interface IAzureStoreSubscription : IData, IEntityFrameworkProvided {}
 public class AzureStoreSubscriptionWrapper : AzureStoreSubscription, IAzureStoreSubscription { }

 using (var c1 = new C1AzureStoreRPContext("opencms-sql-connection"))
 {
    var wrap = new DbSetWrapper<IAzureStoreSubscription, AzureStoreSubscriptionWrapper>(c1);
    Log.LogInformation("EF", string.Format("hello {0}", wrap.Data.ToList().Count));
 }

I don't want to pull all the data to memory and do the cast their, is there no other solution?

like image 651
Poul K. Sørensen Avatar asked Nov 30 '13 11:11

Poul K. Sørensen


1 Answers

IQueryable<T> is covariant so instead of attempting to cast the DbSet<SubType> to DbSet<SuperType>, simply assign:

Data = context.Set<Entity>(); // .AsQueryable() not needed but does make it more readable

This, of course, depends on Entity implementing C1Data, which is not guaranteed based on your generic class definition (which is not good). To fix this, change your type constraint for Entity as follows:

where Entity: C1Data
like image 80
Moho Avatar answered Oct 11 '22 05:10

Moho