动态获取 DbContext 中 Dbset 的行数

Posted

技术标签:

【中文标题】动态获取 DbContext 中 Dbset 的行数【英文标题】:Get Row Count of Dbset in DbContext dynamicly 【发布时间】:2017-12-10 14:09:01 【问题描述】:

我有一个表单,它将我的DbContext 的实例和表的实体传递给它,如下所示:

public frm_foo(DbContext DatabaseContext, DbSet TableEntity)
        
           InitializeComponent();
           var res =GetRowCount(DatabaseContext,TableEntity);
        

并通过以下方式致电表单承包商:

new frm_foo(dbContext, dbContext.Set<IpRoom>()).ShowDialog();

上下文包含一个IpRoom 表。

我想从将DbContextDbset 实例发送给它的函数中获取行数,如下所示:

public int GetRowCount(DbContext DatabaseContext, DbSet TableEntity)
   
       var countVal = (from a in DatabaseContext.Set(TableEntity.GetType())
                        select a).Count();
       return countVal;
   

但出现错误:

找不到源类型的查询模式的实现 '数据库集'。未找到“选择”。

DatabaseContext.Set(TableEntity.GetType()) 返回一个数据库集!有人知道我怎么了?提前致谢

Ps:我不想使用SqlQuery,类似:

var sql = "SELECT COUNT(*) FROM dbo.IpRoom";
var total = context.Database.SqlQuery<int>(sql).Single();

【问题讨论】:

Could not find an implementation of the query pattern的可能重复 看看这个方法的预期用途会很有趣,即GetRowCount(context, ???) @IvanStoev:???Ivan 是什么?你的意思是传递一个参数给函数? 否 :) 问题是如何获得 DbSet 以便将其传递给方法。只是想知道为什么你需要那个方法,因为例如context.Logs.Count() 很容易做到这一点。 嗯,我不确定。现在我看到了您的更新,并且以某种方式可以解决Count 问题,但请注意非通用DbSet 几乎无法使用。您不能针对它编写普通的 LINQ,ToList 等也不能。如果您绝对确定问题只是 Count(),我想我们可以提供帮助。 【参考方案1】:

DbSet 不实现 IQueryable,DbSet&lt;T&gt; 实现。例如

public static int GetRowCount<T>(DbContext DatabaseContext, DbSet<T> TableEntity)

    var countVal = TableEntity.Count();
    return countVal;

【讨论】:

它会生成此错误:类型“T”必须是引用类型才能将其用作泛型类型或方法“DbSet”中的参数“TEntity” 对。 T 应该是在您的 DbContext 子类中定义的实体类型。也许您应该更详细地解释您要完成的工作。 我解释了更多问题大卫。你能看一下吗? 再次阅读问题。仍然不知道你想做什么。也许简短而完整的复制会有所帮助。 事实上我是在表格中对Dbcontex 中的表格执行一些操作...例如表格行数...或过滤某些行并将其显示给最终用户...因此,我发送了一个 dbcontextdbset 的实例,女巫必须从中计算或过滤【参考方案2】:

我使用类似这样的函数来了解表格是否没有元素并且需要用数据播种才能使用:

using System;
using System.Linq;

namespace EFCoreTutorial

    class Program
    
        static void Main(string[] args)
            
            using (var context = new Data.SchoolContext())
            
                var studentsCount = context.Students.Count();

                if (studentsCount == 0)
                
                    // Seed all your starting data now
                    var student = new Model.Student()
                    
                        Name = "Ali",
                    ;

                    context.Students.Add(student);
                    context.SaveChanges();
                
            
        
    

SchoolContext 派生自 DbContext。

【讨论】:

【参考方案3】:

要获得通用行数,我使用以下方法。

public static int GetRowCount<T>(DbContext context)
    
        // Get the generic type definition
        var method = typeof(DbContext).GetMethod(
            nameof(DbContext.Set), BindingFlags.Public | BindingFlags.Instance);

        // Build a method with the specific type argument you're interested in
        method = method.MakeGenericMethod(typeof(T));

        var iEnumerable = method.Invoke(context, null) as IQueryable<T>;

        return (iEnumerable ?? throw new InvalidOperationException()).Count();
    

【讨论】:

【参考方案4】:

为您的项目添加一个类作为打击:

namespace System.Data.Entity

  public static class EntityFrameworkExtensions
  
    public static IEnumerable<object> AsEnumerable(this DbSet set)
    
      foreach (var entity in set)
        yield return entity;
    
  

这个类添加一个通用方法AsEnumerableDbSet 实例,当你想使用它时,例如Count

 var count = (from a in TableEntity.AsEnumerable() select a).Count();

【讨论】:

这是个坏主意,因为它会导致 DbSet 中的所有实体都加载到内存中,而不是在 DB 中运行计数。 这特别慢。

以上是关于动态获取 DbContext 中 Dbset 的行数的主要内容,如果未能解决你的问题,请参考以下文章

DbContext运行时动态附加上一个dbset

.Net使用配置文件 DbContext 动态加载 DbSet

我可以克隆一个 IQueryable 以在另一个 DbContext 的 DbSet 上运行吗?

EF dbcontext 在 dynamo 自定义节点中返回一个空的 dbset

DbContext.set() 无法为实体创建 DbSet,因为此类型未包含在上下文的模型中

在构造函数中存储DbSet而不是调用DbContext.Set 适合各种用途