2016-01-24 114 views
0

我试图让Entity Framework为自定义查询返回多个结果,然后将它映射回Entity Framework Code First模型。是否有可能使用Entity Framework的内部映射引擎?如何让实体框架映射DbDataReader?

我可以保证结果集中两个查询返回的行直接映射到EF模型。作为内部要求,我无法使用存储过程。

public void MultipleResultSets() 
{ 
    var db = new DbContext(); 
    var command = db.Database.Connection.CreateCommand(); 
    command.Connection.Open(); 
    command.CommandText = 
     @" 
     SELECT * FROM TableA; 
     SELECT * FROM TableB; 
     "; 

    using (var reader = command.ExecuteReader()) 
    { 
     // Map Table A rows 
     var tableARows = new List<TableARow>(); 
     while (reader.Read()) 
      tableARows.Add(reader.Map<TablARow>()); // "Map()" is not real 

     reader.NextResult(); 

     // Map Table B rows 
     var tableBRows = new List<TableBRow>(); 
     while (reader.Read()) 
      tableARows.Add(reader.Map<TablBRow>()); // "Map()" is not real 
    } 
    command.Connection.Close(); 
} 
+0

为什么你需要这个成为一个返回多个结果集而不是仅发送两个查询的查询? – Pawel

+0

@Pawel,减少数据库往返次数。 – Omar

+1

不知道它是否值得,但可以将每个结果集公开为DbDataReader并使用ObjectContext.Translate方法 – Pawel

回答

2

免责声明:我的项目EF+的所有者。

这是一个扩展方法,您可以从我的存储库中找到使用内部映射引擎映射数据读取器的方法。

public static IEnumerable<T> MapReader<T>(this DbContext context, DbDataReader reader) where T : class 
{ 
    return ((IObjectContextAdapter) context).ObjectContext.Translate<T>(reader);  
} 

然后,您可以使用您的代码是这样的:

public void MultipleResultSets() 
{ 
    var db = new DbContext(); 
    var command = db.Database.Connection.CreateCommand(); 
    command.Connection.Open(); 
    command.CommandText = 
     @" 
     SELECT * FROM TableA; 
     SELECT * FROM TableB; 
     "; 

    using (var reader = command.ExecuteReader()) 
    { 
     // Map Table A rows 
     var tableARows = db.MapReader<TableA>(reader); 

     reader.NextResult(); 

     // Map Table B rows 
     var tableBRows = db.MapReader<TableB>(reader); 
    } 
    command.Connection.Close(); 
} 

注意:扩展方法已更新为使用帕维尔回答“ObjectContext.Translate”

+0

这看起来很棒。我试着运行它对我的一个表,并收到关于一个可为空的十进制列以下错误(注意,我使用MySQL)。请参阅http://pastebin.com/HRvqtRbR上的堆栈跟踪 EntityFramework.dll中发生未处理的类型为“System.InvalidOperationException”的异常 其他信息:'TableA'上的'ColumnA'属性不能设置为'System.String'的值。您必须将此属性设置为“System.Decimal”类型的非空值。 – Omar

+0

我用MySQL进行了测试,效果很好。此方法与SqlQuery 具有相同的限制,因此请尝试将其用于每个查询以检查问题是否与您的查询之一相关:“db.Database.SqlQuery (”SELECT * FROM TableA“)。ToList();” –

+0

使用'Translate'方法处理之前无法使用的查询。 – Omar