首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果使用DbContext,如何为EfCore.BulkExtensions创建接口

如果使用DbContext,如何为EfCore.BulkExtensions创建接口
EN

Stack Overflow用户
提问于 2018-05-13 17:47:04
回答 2查看 2.4K关注 0票数 0

我正在开发一个使用实体FrameworkCore2.0的ASP.Net Core2.0API。我试图使用XUnit和Moq构建单元测试,但在为DbContext创建接口时遇到了问题,以便在单元测试中模拟它。

目前,我的项目没有为我的上下文使用接口。我将它作为其实现注入到存储库类中。在我的Startup.cs中,我使用services.AddDbContext来设置它。

典型存储库类构造函数的示例。

代码语言:javascript
复制
    public CompaniesRepository(MyDbContext myDbContext)
    {
        _myDbContext = myDbContext;
    }

Startup.cs实例

代码语言:javascript
复制
        services.AddDbContext<MyDbContext>(options =>
        {
            options.UseSqlServer(Configuration.GetConnectionString("MyDbConnectionString"),
            sqlOptions =>
            {
                sqlOptions.EnableRetryOnFailure(5,TimeSpan.FromSeconds(30),sqlTransientErrors);
            });
        });

这种方法一直运作得很好。

然而,现在我正在尝试设置单元测试,我希望能够伪装我的上下文,所以我需要为它创建一个接口。

因此,我向MyDbContext添加了一个名为IMyDbContext的接口,并在Startup.cs中添加了以下代码,如下所示

代码语言:javascript
复制
        services.AddScoped<IMyDbContext>(provider => provider.GetService<MyDbContext>());

似乎起作用了,除了一个问题。我还使用Boris的EFCore.BulkExtensions NuGet,因此,我从存储库类中得到一个编译错误,它现在将IMyDbContext接口注入构造函数中,声明我的接口不包含BulkInsert的定义。

Error CS1929 'IMyDbContext‘不包含'BulkInsert’的定义,最好的扩展方法重载BulkInsert IList、BulkConfig、Action)‘需要一个'DbContext’类型的接收方。

我假设我需要以某种方式将BulkInsert扩展方法添加到我的IMyDyBontext接口中,但我不知道如何正确地做到这一点。如果我只是尝试将该方法添加到我的接口中,那么我就会发现一个错误,它不是在我的MyDbContext类中实现的。

如何在我的BulkInsert类中引用MyDbContext扩展方法?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-05-13 19:02:51

BulkInsert是一种扩展方法。您不能轻松地模拟静态方法。

相反,您可以在MyDbContext类中实现它。然后,您可以模拟IMyDbContext进行单元测试。注:我没有测试它。

代码语言:javascript
复制
public interface IMyDbContext
{
    void BulkInsert<T>(IList<T> entities, BulkConfig bulkConfig = null,
        Action<decimal> progress = null) where T : class;

}

public class MyDbContext : DbContext, IMyDbContext
{
    public void BulkInsert<T>(IList<T> entities, BulkConfig bulkConfig = null,
        Action<decimal> progress = null) where T : class
    {
        this.BulkInsertOrUpdate(entities, bulkConfig, progress);
    }
}
票数 2
EN

Stack Overflow用户

发布于 2019-03-18 19:32:41

最近,我在准备在使用EF包时模拟我的DbContext进行单元测试时遇到了这个问题。标记为正确答案的响应是,几乎是正确的(尽管他们确实说没有测试他们的代码)。

当以上述方式在DbContext类中实现这一功能时,您将在调用BulkInsert方法时收到一个BulkInsert。

因此,我开始调试,并决定在DbContext类中的方法上放置一个断点,以查看发生了什么。这使我理解了StackOverflowException的原因:由于" This“关键字的范围,该方法正在调用自身而不是基类DbContext类上的方法。

解决方案相当简单,通过对BulkInsert实现中的MyDbContext方法实现进行以下更改来解决:

代码语言:javascript
复制
public async Task BulkInsertAsync<T>(IList<T> entities, BulkConfig bulkConfig = null, Action<decimal> progress = null) where T : class
{
    await ((DbContext)this).BulkInsertAsync<T>(entities, bulkConfig, progress);
}

另外,将以下行添加到您的IMyDbContext接口:

代码语言:javascript
复制
Task BulkInsertAsync<T>(IList<T> entities, BulkConfig bulkConfig = null, Action<decimal> progress = null) where T : class;

这确保了将" This“的范围转换为基本的DbContext类类型,而不是我自己的DbContext实现的类型。因此,它没有调用自己,而是使用基类DbContext调用扩展方法。

使用此解决方案,您现在应该能够在代码中成功地使用扩展方法,如下所示:

代码语言:javascript
复制
await _context.BulkInsertAsync<User>(users);

希望有人能找到有用的东西。通过调试解决这个问题并不是太糟糕,并且确保了在使用BulkExtensions包时,我可以轻松地保持所有方法的可测试性!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50318941

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档