实现通用 DbContext 服务

Posted

技术标签:

【中文标题】实现通用 DbContext 服务【英文标题】:Implementing a generic DbContext service 【发布时间】:2020-01-21 18:15:51 【问题描述】:

我有一个通用接口,我想在我的代码中全面实现它,尽管实现可能在某些继承级别上有所不同。我这样做是因为我一直在为我所做的每个项目编写此代码而且我厌倦了一直编写相同的代码而几乎没有调整。

我创建了这个界面:

/// <summary>
// A generic interface for implementing the basic database operations.
// This interface can easily be implemented with custom user logic.
// The KId generic parameter is the primary key of the associated entity and the TEntity
// refers to the entity type.
// </summary>
// <typeparam name = "K" > The primary key of the entity.</typeparam>
// <typeparam name = "TEntity" > The type of entity.</typeparam>
public interface IGenericEntity<K, TEntity>

    // ........Definition codes...............

虽然我可以在不同级别的所有服务实现类中实现这一点,但我可能会编写一些在其他服务实现中相同的东西。

我现在决定创建一个名为 GenericEntityImplementation 的类,我将实现 IGenericEntity。

    public class GenericEntityImplementation<K, TEntity, TDbContext> : 
        IGenericEntity<K, TEntity> where TDbContext : DbContext
    
        private readonly TDbContext _DbContext;

        public GenericEntityImplementation(TDbContext DbContext)
        
            _DbContext = DbContext;
        

/*1 */  public virtual async Task<OperationResult> DeleteAsync(Expression<Func<TEntity, bool>> expression)
/*2 */  
/*3 */      Task TaskResult = await _DbContext.Set<TEntity>().RemoveRange<TEntity>(expression);
/*4 */      if (TaskResult.Status == TaskStatus.RanToCompletion)
/*5 */      
/*6 */          return new OperationResult()
/*7 */          
/*8 */              Message = "",
/*9 */              ReturnObject = null,
/*10*/              Status = OperationStatus.Deleted,
/*11*/              Succeeded = true
/*12*/          ;
/*13*/      
/*14*/  
    

K 是键类型TEntity 可以是数据库类,或者更确切地说是要搭建的数据库表TDbContextDbContext 类型,如上所示。

从上面可以看出,我已经将一个虚拟 DbContext 传递给了我想要在这一层执行所有数据库操作的类。但是由于我一直在尝试,但是从第 3 行可以看出,编辑器显示我的代码有一些问题(红色下划线)。

我的问题是有人可以向我解释如何告诉传递给类的 DbContext 我在任何情况下尝试引用的实体类型,就像我在下面的代码中可以做的那样?

public class ViewDbContext : IdentityDbContext

    public HotelDbContext(DbContextOptions<HotelDbContext> options) : base(options)
    
    

    public DbSet<View> Views  get; set; 



public class ViewsService

    private readonly ViewDbContext _DbContext;

    public GenericEntityImplementation(ViewDbContext DbContext)
    
        _DbContext = DbContext;
    

    public virtual bool Any()
    
        return _DbContext.Views.Any() ? true : false;
    

【问题讨论】:

由于我们看不到您的编辑器,您能否将第 3 行显示的错误包括在内? ? true : false 是多余的。与简单地调用 .Any() 相比,它没有任何好处,尤其是当调用它的方法具有相同的名称时。 是的,但这很简单。我所有的代码都在这里被清除了。您只需将它们复制并粘贴到一个命名空间中即可,一切都会好起来 【参考方案1】:

正如上面评论的那样,我在编辑器上收到的错误是: 'TEntity' 必须是引用类型才能将其用作泛型类型或方法'DbContext.Set()' 中的参数'TEntity' 但在那之后,我的脑海里闪过一些东西,我把这条线放在了顶部,现在一切都很完美。 where TEntity : class

public class GenericEntityImplementation<K, TEntity, TDbContext> : 
        IGenericEntity<K, TEntity> where TDbContext : DbContext where TEntity : class


【讨论】:

以上是关于实现通用 DbContext 服务的主要内容,如果未能解决你的问题,请参考以下文章

autofac 多个dbcontext 上下文不一致

3.Context

DbContext 的通用合并:如何检查实体是不是已附加?

EF DbContext 和 ObjectContext 转换

没有给出与所需形式参数 'context of GenericRepository<Incident>.GenericRepository(dbContext) 相对应的参数

DbContext通用数据仓储类