如何将DbContext实现为接口?最终目标是使用 Moq 进行单元测试

问题描述 投票:0回答:3

这是我到目前为止无法运行的代码。我已经完成了我的理解允许的所有研究。 我可能会错过一些愚蠢的东西。我是 c# 和 .Net 环境的新手。

LibraryContext 类一切都很好。问题是我无法使用该界面。当我将其作为服务加载到 Startup.cs 中,然后在控制器中调用它时,会出现错误。使用

Startup.cs
BooksController.cs
片段更新问题。

第一个错误位于

LibraryContext.cs

LibraryContext' does not implement interface member 'ILibraryContext.SaveChangesAsync()' [LibraryApi]. 

然后在

BooksController.cs

'ILibraryContext' does not contain a definition for 'Entry' and no accessible extension method 'Entry' accepting a first argument of type 'ILibraryContext' could be found (are you missing a using directive or an assembly reference?) [LibraryApi]csharp(CS1061) 

...

LibraryContext.cs

public interface ILibraryContext : IDisposable
  {
    public DbSet<Reader> Readers { get; set; }
    public DbSet<Book> Books { get; set; }

    Task<int> SaveChangesAsync();
  }


  public class LibraryContext : DbContext, ILibraryContext
  {
    public LibraryContext(DbContextOptions<LibraryContext> options)
          : base(options)
    {
    }

    public virtual DbSet<Reader> Readers { get; set; }
    public virtual DbSet<Book> Books { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
      modelBuilder.Entity<Book>().ToTable("Book");
      modelBuilder.Entity<Reader>().ToTable("Reader");
    }
  }

Startup.cs

    {
      services.AddScoped<ILibraryContext>(provider => provider.GetService<LibraryContext>());
    ...
    }

BooksController.cs

  {
    private readonly ILibraryContext _context;

    public BooksController(ILibraryContext context)
    {
      _context = context;
    }
...
c# asp.net entity-framework-core
3个回答
1
投票

不,“LibraryContext”类并不是一切都很好。线索就在错误消息中:

LibraryContext' does not implement interface member 'ILibraryContext.SaveChangesAsync()' 

您可以这样添加:

async Task<int> SaveChangesAsync() => await base.SaveChangesAsync(); 

async Task<int> SaveChangesAsync() => base.SaveChangesAsync(); 


1
投票

您可能期望基类

SaveChangesAsync
中的
DbContext
能够履行接口契约,但接口并不是这样工作的。

您可以在

SaveChangesAsync
中添加
LibraryContext
的实现,它只调用
base.SaveChangesAsync
并返回其结果,从而履行接口契约。


0
投票

为了扩展 Johan Donne 的答案,在我的

DbContext
中,我总是用
 包裹 
SaveChangesAsync

public async Task<int> TrySaveAsync(string message = null, bool clearChangeTracker = true)
{
    try
    {
        return await SaveChangesAsync();
    }
    catch (Exception e)
    {
        if(clearChangeTracker) ChangeTracker.Clear();

        //do your exception handling here

        return -1;
    }
}

所以你可以让这个电话成为你的

interface
的一部分:

Task<int> TrySaveAsync(string message = null, bool clearChangeTracker = true);

然后在我的

Controller
或任何地方,如果受影响的行数是
-1
,我就知道出了问题,并且可以根据当前的需求进行处理。

© www.soinside.com 2019 - 2024. All rights reserved.