使用接口的DbContext与子查询导致问题与子、接口、问题、DbContext

2023-09-05 03:27:17 作者:何日成仙

我使用了的DbContext接口,所以我可以写单元测试,我的服务层出这取决于具体的DbContext。这似乎并没有很好地工作,当有子查询中的LINQ语句。

I am using an interface for DbContext so that I can write unit tests for my Service Layer with out depending on concrete DbContext. This doesn't seem to work well when there are sub-queries in LINQ statements.

下面是一个简单的测试,我把测试EF5。

Here is a simple test that I put to test EF5 .

我宣布一个接口,用于我的数据库上下文

I declared an interface for my Db Context

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实现上述接口

And then my SchoolEntities implements the above interface

public partial class SchoolEntities : DbContext, ISchoolContext

下面code抛出一个错误System.NotSupportedException:无法创建类型的常量值'TestEF.Course只有基本类型或枚举类型,在这方面的支持。

The below code throws an error "System.NotSupportedException: Unable to create a constant value of type 'TestEF.Course'. Only primitive types or enumeration types are supported in this context".

*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;

以上code工作正常,如果我取代ISchoolContext声明与SchoolEntities。

The above code works fine if I replace ISchoolContext declaration with SchoolEntities.

SchoolEntities ctx = new SchoolEntities()

注:另外,code正常工作,在EF6接口。这是否意味着这是EF5一个错误?如果这是一个错误是没有任何黑客攻击吗?

Note: Also the code works fine with interface in EF6. Does this mean that this is a bug in EF5? If it is a bug is there any hack for this?

感谢您阅读长的帖子。

推荐答案

您遇到一个非常怪异的行为。你可以试试这个查询与你的榜样?它应该等于你的,但使用的是左连接。

You are encountering a very weird behavior. Could you try this query with your example ? It should be equal to yours but using a left join.

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;

让我知道,如果它的工作原理与接口。

Let me know if it works with the interface.

编辑:

很高兴听到这个查询工作。我无法与EF5重现该问题。你能重新安装EF5 5.0.0?

Good to hear this query works. I wasn't able to reproduce the issue with EF5. Could you reinstall EF5 5.0.0 ?

对于这一点,请打开包管理器控制台(在菜单工具可用>的NuGet包管理器)来运行这个命令:

For that, please open a Package Manager Console (available in the menu Tools > NuGet Packet Manager) to run this command:

PM>安装,包装的EntityFramework -Version 5.0.0

PM> Install-Package EntityFramework -Version 5.0.0

这上面的线可以在的NuGet的官方网站。

EDIT2:

测试你的code之后,我能够重现问题。我看到了异常被抛出时System.Data.Objects.ELinq.Ex$p$pssionConverter.ConstantTranslator.TypedTranslate(Ex$p$pssionConverter父母,ConstantEx pression LINQ)。使用反编译器,我能够找到抛出行 NotSupportedException异常

After testing your code, I was able to reproduce the issue. I saw the exception was thrown at System.Data.Objects.ELinq.ExpressionConverter.ConstantTranslator.TypedTranslate(ExpressionConverter parent, ConstantExpression linq). Using a decompiler, I was able to find the line that throws the NotSupportedException.

然后,我比较此功能EF5和EF6。下面是结果:

Then, I compared this function with EF5 and EF6. Here is the result: .

我不能说为什么这个错误发生,但我怀疑EF5的实现还不能处理你的情况,很遗憾。

I'm unable to say why this error occurs, but I suspect the implementation of EF5 doesn't handle your case, unfortunately.

我想你的code与code-第一的方针,并取得了成功。这个问题必须进行相关的设计方法(EDMX)。

I tried your code with the code-first approach and it succeeded. This issue must be related to the designer approach (EDMX).