![](/img/trans.png)
[英]Entity Framework Core 3: Interface on DBContext good practice?
[英]Creating an Interface for an Entity Framework Core DbContext so that it can be injected/tested?
我有一個相當基本的 Entity Framework Core DbContext 用於我的應用程序。 我正在注入此上下文,但我想進一步解耦上下文,以便我可以進行測試和/或將其替換為不同的上下文/數據庫。
為 DbContext 創建適當接口的最佳實踐方法是什么?
我的數據庫上下文:
public partial class MyContext : DbContext
{
private string _connectionString;
public MyContext(DbContextOptions<MyContext> options) : base(options){}
public MyContext(string connectionString) => _connectionString = connectionString;
public virtual DbSet<Address> Addresses { get; set; }
public virtual DbSet<Person> Persons{ get; set; }
public virtual DbSet<Detail> Details{ get; set; }
public virtual DbSet<Order> Orders { get; set; }
...(about 35 additional tables)
}
在我的界面中,我是否需要為每個 DbSet 公共成員創建一個成員? 有沒有辦法讓界面更簡單?
然后我需要為每個成員創建一個接口嗎? 然后是這些成員的子成員的接口,等等......(我需要到 go 的兔子洞多遠?)
您不需要為數據庫中的每個所需表指定一個 DBSet。 唯一需要 DBSet 的表是您計划直接訪問的表。 在 EF Core 中,您的實體應該在對象之間建立關系,以便您可以執行更復雜的查詢。 例如,您可能永遠不需要拼命訪問訂單的詳細信息,您應該能夠檢索訂單及其詳細信息以檢索/更改您需要的內容(通過 context.Orders.Include(x => x.Details) 之類的命令.FindAsync(id))。
如果您要測試 DbContext,我建議您使用 Moq.EntityFrameworkCore 庫https://github.com/MichalJankowskii/Moq.EntityFrameworkCore 。 它是最接近復制 DbContext 工作方式的能力。 也可以啟動一個內存數據庫進行測試,您可以在此處閱讀: https://docs.microsoft.com/en-us/ef/core/providers/in-memory/?tabs=dotnet-核心-cli 。
我不建議在測試時不先評估支持 DBContext 的可用選項就嘗試從 DbContex 抽象回接口。
EF 的設計理念是您將更換提供程序進行測試,而不是用其他東西替換 DbContext。 如果您確實想通過 DbContext 對存儲庫抽象進行編程,這樣的事情還不錯:
public interface IRepository : IDisposable
{
void Add<TEntity>(TEntity entity) where TEntity : class;
void Update<TEntity>(TEntity entity) where TEntity : class;
void Remove<TEntity>(TEntity entity) where TEntity : class;
IQueryable<TEntity> Query<TEntity>() where TEntity : class;
TEntity GetById<TEntity, TId>(TId id) where TEntity : class;
int SaveChanges();
}
在您的 DbContext 中實現如下:
void IRepository.Add<TEntity>(TEntity entity)
{
Add(entity);
}
void IRepository.Update<TEntity>(TEntity entity)
{
Update(entity);
}
void IRepository.Remove<TEntity>(TEntity entity)
{
Remove(entity);
}
IQueryable<TEntity> IRepository.Query<TEntity>()
{
return Set<TEntity>();
}
TEntity IRepository.GetById<TEntity, TId>(TId id)
{
var entity = Set<TEntity>().Find(id);
if (entity == null)
throw new InvalidOperationException($"No Entity {typeof(TEntity).Name} found for id {id}");
return entity;
}
int IRepository.SaveChanges()
{
return this.SaveChanges();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.