在使用Entity Framework执行多个原始查询后,如何读取多个数据集?

时间:2018-01-24 23:28:54

标签: c# sql-server entity-framework

我有多个依赖于多个临时表的查询,一旦执行完毕,我需要返回多个数据集并映射到C#对象。

这是一个例子

  

我的实际查询更加复杂和冗长,这就是我需要使用temp的原因   为了简单起见,为了简单起见我将它们剪下来

/** START OF SECTION 1 **/
-- Create a temp table
SELECT 
 Id
,Name
INTO #titles 
FROM Titles
WHERE column1 = 'abc';

-- Add an index on the temp table
CREATE INDEX Id #titles(Id);
/** END OF SECTION 1 **/


/** START OF SECTION 2 **/
-- This is the first result set
SELECT 
 t.*
,b.*
FROM OtherRecords as b
INNER JOIN #titles AS t ON t.Id = b.TitleId;
/** END OF SECTION 2 **/



/** START OF SECTION 3 **/
-- This is the second result set
SELECT 
 t.*
,b.*
FROM YetOtherRecords as b
INNER JOIN #titles AS t ON t.Id = b.TitleId;
/** END OF SECTION 3 **/

DROP TABLE #titles;

如您所见,我正在执行多个查询,最终结果是我需要映射到C#模型的两个数据集。

我尝试将上述“按部分分隔”的查询执行到多个实体框架命令中,如此

context.Database.ExecuteSqlCommand("Queries from section 1 above");
var records = context.Database.SqlQuery<OtherRecord>("Queries from section 2 above").ToList();
var otherRecords = context.Database.SqlQuery<YetOtherRecord>("Queries from section 3 above").ToList();

但是这不起作用,因为每个命令都会发出一个新的数据库连接,因此临时表只能用于第一个查询(即context.Database.ExecuteSqlCommand("Queries from section 1 above")。)

如何在上面运行所有查询但是生成两个数据集而不必在每次调用时创建临时表?

1 个答案:

答案 0 :(得分:1)

Microsoft's example学习

您需要创建一个DbDataReader并从中读取记录,因为这样可以从结果集中读取行,然后通过调用NextResult()移动到后续结果集。即使结果集为空,也会为存储过程中的每个SELECT设置一个结果集。

然后,您将上下文转换为IObjectContextAdapter并调用IObjectContextAdapter.ObjectContext.Translate<TEntity>以创建包含从每行创建的对象的ObjectResult<TEntity>。为了做到这一点,返回的列名必须与它所填充的类的属性相匹配。

(微软的例子并没有处理它的IDisposables。也许这就是原因。)

// Just some class with two lists to contain the results.
var result = new ContainsTheResults();

using (var db = new YourDbContext())
{
    using (var cmd = db.Database.Connection.CreateCommand())
    {
        cmd.CommandText = "[dbo].[YourProcedureName]";
        try
        {
            db.Database.Connection.Open();
            using (var reader = cmd.ExecuteReader())
            {

                // Translate the rows in the current result set to a collection of objects
                using (var otherRecords = ((IObjectContextAdapter)db)
                    .ObjectContext
                    .Translate<OtherRecord>(reader, "OtherRecords", MergeOption.AppendOnly))
                {
                    result.OtherRecords = otherRecords.ToList();
                }

                // Go to the next result and read those
                reader.NextResult();
                using (var yetOtherRecords = ((IObjectContextAdapter)db)
                    .ObjectContext
                    .Translate<YetOtherRecord>(reader, "YetOtherRecords", MergeOption.AppendOnly))
                {
                    result.YetOtherRecords = yetOtherRecords.ToList();
                }                     
            }
        }
        finally
        {
            db.Database.Connection.Close();
        }
    }
}

return result;