我正在使用 EF Core 6,我的 DbContext 看起來像這樣:
public class SpaceBattlesDatabase: DbContext, ISpaceBattlesDataBase
{
public DbSet<Building> Buildings => Set<Building>();
// other irrelevant code
}
我想用一個介面抽象它,在一個干凈的架構中的中心層使用..
public interface ISpaceBattlesDataBase
{
public IQueryable<Building> Buildings { get; }
}
但是編譯器警告我:
錯誤 CS0738“SpaceBattlesDatabase”未實作介面成員“ISpaceBattlesDataBase.Buildings”。“SpaceBattlesDatabase.Buildings”無法實作“ISpaceBattlesDataBase.Buildings”,因為它沒有匹配的回傳型別“IQueryable”。
但根據檔案和元資料,DbSet<TEntity>
應該實作IQueryable<TEntity>
..
IEnumerable<T>
也不起作用..我在這里錯過了什么嗎?
我怎樣才能抽象出DbSet
在界面中使用?
謝謝
uj5u.com熱心網友回復:
我在這里錯過了什么嗎?
是的,正如 Eric Lippert在這里解釋的那樣, C# 不支持虛擬方法回傳型別協方差。在這種特殊情況下,您可以使用顯式介面實作來解決:
public class SpaceBattlesDatabase: DbContext, ISpaceBattlesDataBase
{
public DbSet<Building> Buildings => Set<Building>();
IQueryable<Building> ISpaceBattlesDataBase.Buildings => Buildings;
}
public interface ISpaceBattlesDataBase
{
IQueryable<Building> Buildings { get; }
}
uj5u.com熱心網友回復:
在這些情況下,我使用不同的方法。我首先創建一個ContextFactory
:
public class ContextFactory : IDesignTimeDbContextFactory<ApplicationDbContext>
{
public ApplicationDbContext CreateDbContext(string[]? args = null)
{
return new ApplicationDbContext();
}
}
然后我創建一個IDataService
界面:
public interface IDataService<T>
{
Task<IEnumerable<T>> GetAll();
Task<T> Get(int id);
Task<T> Create(T entity);
Task<bool> CreateMultiple(List<T> entity);
Task<bool> Delete(T entity);
Task<T> Update(T entity);
}
并像這樣實作它:
public class DataService<T> : IDataService<T> where T : class
{
private readonly ContextFactory contextFactory;
public DataService(ContextFactory contextFactory)
{
this.contextFactory = contextFactory;
}
public async Task<T> Create(T entity)
{
using ApplicationDbContext context = contextFactory.CreateDbContext();
EntityEntry<T> createdResult = await context.Set<T>().AddAsync(entity);
await context.SaveChangesAsync();
return createdResult.Entity;
}
public async Task<bool> CreateMultiple(List<T> entity)
{
using ApplicationDbContext context = contextFactory.CreateDbContext();
await context.Set<T>().AddRangeAsync(entity);
await context.SaveChangesAsync();
return true;
}
public async Task<bool> Delete(T entity)
{
try
{
using ApplicationDbContext context = contextFactory.CreateDbContext();
context.Set<T>().Remove(entity);
await context.SaveChangesAsync();
return true;
}
catch (Exception)
{
return false;
}
}
public async Task<T> Get(int id)
{
using ApplicationDbContext context = contextFactory.CreateDbContext();
return await context.Set<T>().FindAsync(id) ?? await new ValueTask<T>();
}
public async Task<IEnumerable<T>> GetAll()
{
using ApplicationDbContext context = contextFactory.CreateDbContext();
return await context.Set<T>().ToListAsync();
}
public async Task<T> Update(T entity)
{
using ApplicationDbContext context = contextFactory.CreateDbContext();
context.Set<T>().Update(entity);
await context.SaveChangesAsync();
return entity;
}
}
您可以根據需要對其進行修改。最后,對于Building
模型,我會做類似的事情:
public class BuildingCrudService
{
private readonly IDataService<Building> dataService;
public BuildingCrudService()
{
dataService = new DataService<Building>(new ContextFactory());
}
/// <summary>
/// Adds a building to the database.
/// </summary>
/// <param name="building"></param>
/// <returns>List of buildings.</returns>
public async Task<List<Building>> AddBuildingAsync(Building building)
{
await dataService.Create(building);
return await ListBuildingsAsync();
}
/// <summary>
/// Deletes the building from the database.
/// </summary>
/// <param name="id"></param>
/// <returns>True if deleted, else false.</returns>
public async Task<bool> DeleteBuildingAsync(int id)
{
Building b = await GetBuildingByIDAsync(id);
return await dataService.Delete(b);
}
/// <summary>
/// Fetches the list of all the buildings from the database.
/// </summary>
/// <returns>List of buildings.</returns>
public async Task<List<Building>> ListBuildingsAsync()
{
return (List<Building>)await dataService.GetAll();
}
/// <summary>
/// Searches for a building that matches the id.
/// </summary>
/// <param name="id"></param>
/// <returns>The building that matches the id.</returns>
public async Task<Building> GetBuildingByIDAsync(int id)
{
return await dataService.Get(id);
}
/// <summary>
/// Updates an existing building to the database.
/// </summary>
/// <param name="building"></param>
/// <returns>The updated building.</returns>
public async Task<Building> UpdateBuildingAsync(Building building)
{
Building b = await GetBuildingByIDAsync(building.BuildingId);
b.Name = building.Name;
// Also update other properties
return await dataService.Update(b);
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/498410.html
上一篇:位圖中的位圖