GWB*_*GWB 10 .net abstraction c#-4.0 entity-framework-4.1
目标:
我正在尝试使用新的Entity Framework 4.1 DbContext API(使用Database First和POCO类的新ADO.NET DbContext Generator)并使用基本的通用存储库提供抽象层.
问题:
如果我尝试在我的存储库中使用子查询,EF无法完成转换并抛出错误:
System.NotSupportedException:LINQ to Entities无法识别方法'System.Linq.IQueryable`1 [EntityFramework41Test.Data.Entity .Table2] Query()'方法,这个方法无法转换成商店表达式.
我过去曾成功地将此设计与旧的4.0 ObjectContext一起使用,但我想使用新的API.使用4.0 ObjectContext API(使用生成的POCO实体进行测试)也会失败.
注意:我认为发布数百行代码并不现实,但我有一个使用SQL Server CE 4.0的ASP.NET MVC 3项目的示例解决方案和一个基本的单元测试项目,演示了各种方法的结果.上传或通过电子邮件发送,如果有帮
我正在使用的存储库接口很简单:
public interface IRepository<TEntity> : IDisposable where TEntity : class, ITestEntity
{
TEntity GetById(int id);
IQueryable<TEntity> Query();
void Add(TEntity entity);
void Remove(TEntity entity);
void Attach(TEntity entity);
}
Run Code Online (Sandbox Code Playgroud)
上下文界面更简单:
public interface ITestDbContext : IDisposable
{
IDbSet<TEntity> Set<TEntity>() where T: class, ITestEntity;
void Commit();
}
Run Code Online (Sandbox Code Playgroud)
以下是使用存储库和上下文实例的接口不起作用的示例用法:
using (ITestDbContext context = new TestDbContext())
using (IRepository<Table1> table1Repository = new Repository<Table1>(context))
using (IRepository<Table2> table2Repository = new Repository<Table2>(context))
{
// throws a NotSupportedException
var results = table1Repository.Query()
.Select(t1 => new
{
T1 = t1,
HasMatches = table2Repository.Query()
.Any(t2 => t2.Table1Id == t1.Id)
})
.ToList();
}
Run Code Online (Sandbox Code Playgroud)
上面的代码是我想要使用的方法.具体的课程最终会被注入.
请忽略这样一个事实,即使用子查询有更好的方法来编写此特定查询.我故意简化代码以专注于实际问题:EF不会翻译查询.
存储"内部"存储库Query()方法结果实际上可以正常工作,但不是理想的,因为您必须记住一直这样做.
using (ITestDbContext context = new TestDbContext())
using (IRepository<Table1> table1Repository = new Repository<Table1>(context))
using (IRepository<Table2> table2Repository = new Repository<Table2>(context))
{
var table2RepositoryQuery = table2Repository.Query();
// this time, it works!
var results = table1Repository.Query()
.Select(t1 => new
{
T1 = t1,
HasMatches = table2RepositoryQuery
.Any(t2 => t2.Table1Id == t1.Id)
})
.ToList();
}
Run Code Online (Sandbox Code Playgroud)
我还注意到其他一些方法破解或成功,例如忽视存储库和调用TestDbContext.Set<TEntity>()工作但ITestDbContext.Set<TEntity>()不会翻译.将定义更改ITestDbContext.Set<TEntity>()为return DbSet<TEntity>而不是IDbSet<TEntity>仍然失败.
编辑:
如果没有一些查询拦截和翻译,我认为这是不可能的.如果我确实在将来找到解决方案,我一定会分享它.
我没有使用 EF 的经验,但基于使用 NHibernate 及其不断发展的 LINQ 支持,我怀疑您的问题的答案是您不喜欢的答案 - 听起来这个特定的构造还不是(还? ) 受 EF LINQ 提供程序支持,并且您需要更改查询。