如何将 DbSet<T> 转换为 List<T>

15

以下是简化的Entity Framework 6上下文,我正在尝试使用反射来将实体填充到List中,但在如何进行转换方面遇到了问题。

public class FooContext : DbContext
{
   public virtual IDbSet<FooClass> Foo { get; set; }    
   //...
}

public class FooClass
{
    public int Id{ get; set; }
    public string Name {get; set; }
    //...    
}

public main()
{
     using (var context = new FooContext())
     {
         var sets = typeof(FooContext).GetProperties().Where(pi => pi.PropertyType.IsInterface && pi.PropertyType.GetGenericTypeDefinition().ToString().ToLower().Contains("idbset"));

         foreach (var set in sets)
         {
             //When I debug and enumerate over 'value' the entire results are shown so I believe the reflection part is OK.
             var value = set.GetValue(context, null);

             //Always returns null. How can I cast DbSet<T> to List<object> or List<T>? 
             var list = value as List<object>();

             //...
         }
     }
}

我正在为一些集成测试编写实用方法。我试图在不使用直接的内联SQL调用(如使用SqlConnection和SqlCommand等)访问数据库的情况下完成此操作(因为数据存储可能更改为Oracle等)。


1
你可以将其转换为 IEnumerable 接口。 - Alexey Nis
2
一个 DbSet<> 不是列表,而且 DbSet<Foo>List<Foo> 都不是 List<object>。你试图做的事情注定会失败。你能澄清一下你的意图吗?你想要做什么? - Marc Gravell
2
DbSet{T} 实现了 IEnumerable{T} 接口。List{T} 有一个构造函数,它接受一个 IEnumerable{T},所以你可以直接使用 new List<T>(dbSet) - Jaanus Varus
1
你的类型检查可能应该是 pi.PropertyType.IsGenericType && pi.PropertyType.GetGenericTypeDefinition() == typeof(IDbSet<>) - Lee
@Lee 注意在调用那个之前必须检查IsGenericType - Marc Gravell
显示剩余7条评论
4个回答

14

IDBSet继承自IQueryable<TEntity>IEnumerable<TEntity>IQueryableIEnumerable,因此您无法直接将其转换为列表。

但是,您可以使用.ToList().ToListAsync()DBSet中获取List<TEntity>的所有实体。

不过,这会在内存中创建实体的副本,因此您应该考虑直接在DBSet上使用LINQ进行操作。


这会导致 SqlNullValueException 异常。 - Dissident Rage

12
//dont forget using System.Linq;
using (var context = new FooContext())
{
   IQueryable<FooClass> rtn = from temp  in context.Foo select temp;
   var list = rtn.ToList();
}

我在尝试检索表中的所有元素时遇到了解析错误。发送列表而不是“IQueryable”解决了这个问题。 - BorisD

7

除了VicYam的回答,这里有一个更简单的方法,并附有详细的解释。

一旦您添加了System.Linq命名空间,您就不再需要获取IQueryable然后转换为List。相反,您将获得DbSet对象上的扩展方法。

这是什么意思?您可以简单地返回DbSet本身,因为它从IEnumerable继承。消费者(可能是开发人员)随后可以执行.ToList或他们可能需要的任何其他列表类型。

最简单的方法

这将按原样返回DbSet,它已经继承了IEnumerable,这是一个列表类型,可以将其转换为List

List<ObjectType> list = new List<ObjectType>();
using (var context = new FooContext())
{
    list = context.Foo;
}

替代方案

你可以直接将 IEnumerable 转换为 List

using (var context = new FooContext())
{
    var list = context.Foo.ToList();
}

仍然想要VicYam的答案,但只需要一行吗?
using (var context = new FooContext())
{
    var list = context.Foo.AsQueryable().ToList();
}

-1
private StudentDatabaseEntities db = new StudentDatabaseEntities();

public List<StudentDatabaseDbTableModel> AllProducts()
{
    return db.StudentDatabaseDbTableModel.ToList();
}   

db.StudentDatabaseDbTableModel 是 DbSet 类型。ToList 是 DbSet 类中的一个方法。ToList 方法将类型为 DbSet 的对象转换为 List 类型。


尽管这段代码片段可能解决了问题,但包括解释能够真正有助于提高您的帖子质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议原因。 - DimaSan
2
在DbSet中没有ToList()方法。 - Bassem Akl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接