EF6 中的这个 Test DBSet 类可以适应 EF Core 吗?

Posted

技术标签:

【中文标题】EF6 中的这个 Test DBSet 类可以适应 EF Core 吗?【英文标题】:Can this TestDBSet class from EF 6 be adapted to work with EF Core? 【发布时间】:2019-07-12 00:52:59 【问题描述】:

我正在尝试按照 EF 6 的本教程编写自己的测试替身来模拟测试实体框架核心:

https://docs.microsoft.com/en-us/ef/ef6/fundamentals/testing/writing-test-doubles

本教程停留在 TestDbSet 类上,该类应该提供 DbSet 的内存实现。但是,大多数成员与 EF Core 不兼容:

public class TestDbSet<TEntity> : DbSet<TEntity>, IQueryable, IEnumerable<TEntity>, IDbAsyncEnumerable<TEntity>
    where TEntity : class

    ObservableCollection<TEntity> _data;
    IQueryable _query;

    public TestDbSet()
    
        _data = new ObservableCollection<TEntity>();
        _query = _data.AsQueryable();
    

    public override TEntity Add(TEntity item)
    
        _data.Add(item);
        return item;
    

    public override TEntity Remove(TEntity item)
    
        _data.Remove(item);
        return item;
    

    public override TEntity Attach(TEntity item)
    
        _data.Add(item);
        return item;
    

    public override TEntity Create()
    
        return Activator.CreateInstance<TEntity>();
    

    public override TDerivedEntity Create<TDerivedEntity>()
    
        return Activator.CreateInstance<TDerivedEntity>();
    

    public override ObservableCollection<TEntity> Local
    
        get  return _data; 
    

    Type IQueryable.ElementType
    
        get  return _query.ElementType; 
    

    Expression IQueryable.Expression
    
        get  return _query.Expression; 
    

    IQueryProvider IQueryable.Provider
    
        get  return new TestDbAsyncQueryProvider<TEntity>(_query.Provider); 
    

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    
        return _data.GetEnumerator();
    

    IEnumerator<TEntity> IEnumerable<TEntity>.GetEnumerator()
    
        return _data.GetEnumerator();
    

    IDbAsyncEnumerator<TEntity> IDbAsyncEnumerable<TEntity>.GetAsyncEnumerator()
    
        return new TestDbAsyncEnumerator<TEntity>(_data.GetEnumerator());
    

Add、Attach、Remove 和 Create 方法发生的错误对于所有四个方法都是一样的:

'TestDbSet.Add(TEntity)':返回类型必须是 'EntityEntry' 匹配被覆盖的成员 'DbSet.Add(TEntity)

谁能解释我是否可以将 转换为 EntityEntry 或者是否有更好的方法来解决这个问题?非常感谢

【问题讨论】:

【参考方案1】:

对于EntityEntry&lt;TEntity&gt;,它表示跟踪的TEntity并检查源代码,它使用StateManagerTEntity转换为EntityEntry&lt;TEntity&gt;

您无法在 TestDbSet&lt;TEntity&gt; 中创建 StateManager

尝试检查以下代码是否适合您。

public class TestDbSet<TEntity> : DbSet<TEntity>, IQueryable, IEnumerable<TEntity>
    where TEntity : class

    ObservableCollection<TEntity> _data;
    IQueryable _query;

    public TestDbSet()
    
        _data = new ObservableCollection<TEntity>();
        _query = _data.AsQueryable();
    

    public override EntityEntry<TEntity> Add(TEntity item)
    
        _data.Add(item);
        var entity = base.Attach(item);
        return entity;
    

【讨论】:

感谢您的回复!我一直在尝试,但是测试在新行“var entity = base.Attach(item);”上中断出现错误“System.NotImplementedException:方法或操作未实现”。还有什么我可能错过的吗? @EliRush*** 您需要与退货实体合作吗?如果没有,请尝试return item as EntityEntry&lt;T&gt;;return null;【参考方案2】:

@Edward 您的解决方案运行良好,通过返回 null 教程现在至少在我的测试中与 EF 核心兼容,感谢您的提示。

TestContext 中的一些修改: - 使用 Microsoft.EntityFrameworkCore.Query.Internal; - 使用 Microsoft.EntityFrameworkCore.ChangeTracking; - 将 IDbAsyncEnumerable 和 IDbAsyncEnumerator 更改为 IAsyncEnumerable 和 IAsyncEnumerator - 添加、删除和附加方法:将返回类型从 TEntity 更改为 EntityEntry,并将每个方法中的最后一条语句更改为返回 null; - 其他一些方法会出现编译错误,删除即可。

【讨论】:

以上是关于EF6 中的这个 Test DBSet 类可以适应 EF Core 吗?的主要内容,如果未能解决你的问题,请参考以下文章

EF6基础系列(12)--- EF进行批量添加/删除

在 EF6 中是不是有可能有一个 DbSet<T> 仅存在于内存中,而其余的是真实表?

EF 6.0 中缺少 DbSet<entity>.Load() 函数

使用带有DbSet的接口,可以使用EF Core吗?

实体框架,查询包含上下文更改的dbset,而不调用保存更改

为啥类 DBSet 的 AsQueryable() 不在 MSDN 文档中?