将DbSet <Entity>转换为其DbSet <IEntity>,而不将所有实体都拉入内存

Pou*_*sen 6 c# linq entity-framework

我的问题是我正在使用的系统需要Data as IQuearable<IEntity>和entityframework给我数据IQueryable<Entity>

这是我需要实现的接口:

public IQueryable<T> GetData<T>() where T : class, IData {}
Run Code Online (Sandbox Code Playgroud)

我有一个创建为context.Set(MyEntityType)的DbSet,其中MyEntityType是typeof(Entity).

我现在一直在尝试一些事情,不知道如何解决这个问题.(它的所有自动生成的代码来自codedom,但在下面做了一个测试,看它可以工作,但还没有工作)

我做了一个测试包装,问题在这里LINQ to Entities only supports casting EDM primitive or enumeration types如果我可以做这项工作,我也可以使我的其他部分工作.

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));
 }
Run Code Online (Sandbox Code Playgroud)

我不想将所有数据都拉到内存并进行转换,是不是没有其他解决方案?

Moh*_*oho 3

IQueryable<T>是协变的,因此不必尝试将DbSet<SubType>to强制转换为DbSet<SuperType>,只需分配:

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

当然,这取决于Entity实现C1Data,而根据您的通用类定义不能保证这一点(这不好)。要解决此问题,请更改类型约束,Entity如下所示:

where Entity: C1Data
Run Code Online (Sandbox Code Playgroud)