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

时间:2015-06-15 12:46:57

标签: c# reflection casting entity-framework-6

鉴于以下简化的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等)。

5 个答案:

答案 0 :(得分:10)

IDBSet继承自IQueryable<TEntity>IEnumerable<TEntity>IQueryableIEnumerable,因此您无法直接将其投放到列表中。 您可以使用List<TEntity>DBSet

获取.ToList()中所有实体的.ToListAsync()var tileBackground = SKSpriteNode(color: UIColor.whiteColor(), size: CGSizeMake(width: screenWidth, height: screenWidth)) tileBackground.name = "tileBackground" tileBackground.position = CGPoint(x: frame.midX, y: frame.midY); self.addChild(tileBackground) var tile = SKSpriteNode(color: UIColor.redColor(), size: CGSize(width: tileSize, height: tileSize)) tile.name = "tile1" tileBackground.addChild(tile)

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

答案 1 :(得分:8)

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

答案 2 :(得分:1)

你无法施展它。只需通过List<T>向您DbSet创建新的ToListAsync<T>()即可 从IQueryable通过异步枚举或简单地同步ToList()

此外,我认为更好地为您的场景创建具体的实现。现在为EF创建。例如,当你开始使用NHibernate时,为它创建测试,依此类推。对于未来的支持将更加简单,然后尝试创建通用的东西,这对于修复和调试来说会更复杂。

仅供参考,您确定不需要这些集成测试吗? 也许更好的测试您的映射/实现正在使用您的数据库。我认为这将是更重要的部分。当然,如果你之前没有这样做过。

答案 3 :(得分:1)

除了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();
}

答案 4 :(得分:0)

<cfset myArray = arrayNew(1)>
<cfloop query="displayQ" >
    <cfquery name="fileListQ" datasource="#REQUEST.datasource#">
        select
            project_id,
            doc_id,
            file_name,
            file_size,
            status,
            status_date,
            timestamp,
            upload_date
        from project_documents
        where
             project_id = "#displayQ.project_id#"
             <cfif bitAnd(SESSION.rights,structFind(rightsList,"RIGHTS_ADMIN")) EQ 0 
                  AND bitAnd(SESSION.rights,structFind(rightsList,"RIGHTS_ENOVIS_PS")) EQ 0 >
                and status = 3
             </cfif>
    </cfquery>
    <cfloop query="fileListQ">
        <tr>
            <CFSET myArray=ArrayAppend(myArray,#fileListQ.doc_id#,"true"); />
            <td><span class="FAKELINK" onClick="doReport('#fileListQ.file_name#','#fileListQ.doc_id#')">
                     #fileListQ.file_name#
                </span>
            </td>
        </tr>
    </cfloop>
</cfloop>

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