我正在为DbContext使用接口,以便我可以根据具体的DbContext编写服务层的单元测试。当LINQ语句中有子查询时,这似乎无法正常工作。
这是我测试EF5的简单测试。
我为我的Db上下文声明了一个接口
public interface IDbContext
{
#region DbContext public properties
DbChangeTracker ChangeTracker { get; }
DbContextConfiguration Configuration { get; }
Database Database { get; }
#endregion
#region DbContext public methods
IEnumerable<DbEntityValidationResult> GetValidationErrors();
DbEntityEntry Entry(object entity);
DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class;
DbSet<TEntity> Set<TEntity>() where TEntity : class;
DbSet Set(Type entityType);
int SaveChanges();
#endregion
}
public interface ISchoolContext : IDbContext,IDisposable
{
DbSet<Course> Courses { get; set; }
DbSet<Department> Departments { get; set; }
}
然后我的SchoolEntities实现上述接口
public partial class SchoolEntities : DbContext, ISchoolContext
下面的代码引发错误“ System.NotSupportedException:无法创建类型为'TestEF.Course'的常量值。在此上下文中仅支持基本类型或枚举类型”。
*ISchoolContext* ctx = new SchoolEntities()
var query = from dep in ctx.Departments where dep.Budget > 0 && !ctx.Courses.Any(c => c.DepartmentID == dep.DepartmentID) select dep.DepartmentID;
如果我用SchoolEntities替换ISchoolContext声明,则以上代码可以正常工作。
SchoolEntities ctx = new SchoolEntities()
注意:该代码也可以在EF6中的接口上正常工作。这是否意味着这是EF5中的错误?如果是错误,是否有任何破解方法?
感谢您阅读冗长的帖子。
最佳答案
您遇到一个非常奇怪的行为。您能否以您的示例尝试此查询?它应该与您的相等,但使用左联接。
var query = from dep in ctx.Departments
join course in ctx.Courses
on dep.DepartmentID equals course.DepartmentID into leftJoin
from courseLeftJoin in leftJoin.DefaultIfEmpty()
where dep.Budget > 0 && courseLeftJoin == null
select dep.DepartmentID;
让我知道它是否适用于该界面。
编辑:
很高兴听到这个查询的作品。我无法使用EF5重现该问题。您可以重新安装EF5 5.0.0吗?
为此,请打开程序包管理器控制台(位于菜单>工具> NuGet数据包管理器中)以运行以下命令:
PM>安装包EntityFramework-版本5.0.0
上面的这一行可以在NuGet的official website上找到。
编辑2:
测试您的代码后,我能够重现该问题。我看到在
System.Data.Objects.ELinq.ExpressionConverter.ConstantTranslator.TypedTranslate(ExpressionConverter parent, ConstantExpression linq)
处引发了异常。使用反编译器,我能够找到引发NotSupportedException
的行。然后,我将此功能与EF5和EF6进行了比较。结果如下:
我无法说出为什么会发生此错误,但是不幸的是,我怀疑EF5的实现无法处理您的情况。
我使用代码优先方法尝试了您的代码,并成功了。此问题必须与设计者方法(EDMX)有关。