我的问题是,我正在使用的系统期望数据为IQuearable<IEntity>
,而entityframework为我提供的数据为IQueryable<Entity>
这是我需要实现的界面:
public IQueryable<T> GetData<T>() where T : class, IData {}
我创建了一个DbSet作为context.Set(MyEntityType),其中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));
}
我不想将所有数据都拉到内存并进行投射,是否有其他解决方案?
答案 0 :(得分:3)
IQueryable<T>
是协变的,所以不要试图将DbSet<SubType>
强制转换为DbSet<SuperType>
,只需指定:
Data = context.Set<Entity>(); // .AsQueryable() not needed but does make it more readable
当然,这取决于Entity
实现C1Data
,这不能保证基于您的泛型类定义(这不好)。要解决此问题,请更改Entity
的类型约束,如下所示:
where Entity: C1Data
答案 1 :(得分:1)
我最终在我的应用程序中使用的代码是:
public IQueryable<T> GetData<T>() where T : class, IData
{
var factory = EntityFrameworkConfiguration.TypeFactory[typeof(T)];
var context = factory.Item2();
ThreadDataManager.GetCurrentNotNull().OnDispose += () =>
{
context.Dispose();
};
var method = typeof(DbContext).GetMethod("Set", new Type[0]).MakeGenericMethod(factory.Item1);
IQueryable<T> genericItem = (IQueryable < T >)method.Invoke(context, new object[0]);
return genericItem;
}
请注意,ThreadDataManager是我正在集成的系统的一部分。