web-dev-qa-db-ja.com

エンティティフレームワークを使用してデータテーブルを返す

エンティティフレームワークを使用しています。アプリケーションには、ストアドプロシージャを使用する必要がある特定の状況が1つあります。 SPには多くのSQLステートメントが記述されているため、C#コードで書き直したくありません。データテーブルの形式で結果を取得するだけです。私は少しのコードを書きましたが、ある時点で行き詰っています。誰かが以下のコードを完成できますか?

using (dbContext.Database.Connection)
{
dbContext.Database.Connection.Open();
DbCommand cmdItems= dbContext.Database.Connection.CreateCommand();
cmdItems.CommandText = "GetAvailableItems";
cmdItems.CommandType = CommandType.StoredProcedure;
cmdItems.Parameters.Add(new SqlParameter("jobCardId", 100525));
//Need to write code below to populate a DataTable.
}
12
user1640256

どうもありがとう。解決しました。解決策は次のとおりです。

using (var context = new DataBaseContext())
{
    var dt = new DataTable();
    var conn = context.Database.Connection;
    var connectionState = conn.State;
    try
    {
        if (connectionState != ConnectionState.Open) conn.Open();
        using (var cmd = conn.CreateCommand())
        {
            cmd.CommandText = "GetAvailableItems";
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.Add(new SqlParameter("jobCardId", 100525));
            using (var reader = cmd.ExecuteReader())
            {
                dt.Load(reader);
            }
        }
    }
    catch (Exception ex)
    {
        // error handling
        throw;
    }
    finally
    {
        if (connectionState != ConnectionState.Closed) conn.Close();
    }
    return dt;
}
17
user1640256

この例では、datatableからデータを選択するEntityFrameworkオブジェクトを返します。

これが目標に対する最善の解決策だと思います。ただし、このソリューションの問題は、各レコードが列挙されることです。 filter最初にリストを作成してから、リストからこれを実行して回避することもできます。

DataTable dt = new DataTable();
(from rec in database.Table.AsEnumerable()
                     select new
                     {
                         id = rec.id,
                         name = rec.Name
                         //etc
                     }).Aggregate(table, (dt, r) =>
                     {
                         dt.Rows.Add(r.id, r.Name);
                         return dt;
                     });
8
John Smith

このソリューションは、シンプルで非常に高速で使いやすいです。

DbContext拡張機能を作成します。

using System.Data;
using System.Data.Common;
using System.Data.Entity;
..
..
public static class DbContextExtensions
{
    public static DataTable DataTable(this DbContext context, string sqlQuery)
    {
        DbProviderFactory dbFactory = DbProviderFactories.GetFactory(context.Database.Connection);

        using (var cmd = dbFactory.CreateCommand())
        {
            cmd.Connection = context.Database.Connection;
            cmd.CommandType = CommandType.Text;
            cmd.CommandText = sqlQuery;
            using (DbDataAdapter adapter = dbFactory.CreateDataAdapter())
            {
                adapter.SelectCommand = cmd;

                DataTable dt = new DataTable();
                adapter.Fill(dt);

                return dt;
            }
        }
    }
}

例:

using (MyDbContext db = new MyDbContext())
{
    string query = db.Students.Where(o => o.Age > 20).ToString();

    DataTable dataTable = db.DataTable(query);

    ..

    DataTable dt = db.DataTable(
                         (  from o in db.Studets
                            where o.Age > 20
                            select o
                         ).ToString()
                    );
}
4
F.Sighinolfi

汎用パラメーター(SQL Server固有ではない)と複数の結果セットのサポートを含む、以前のソリューションを改善するだけです。

    DataSet GetDataSet(string sql, CommandType commandType, Dictionary<string, Object> parameters)
    {
        // creates resulting dataset
        var result = new DataSet();

        // creates a data access context (DbContext descendant)
        using (var context = new MyDbContext())
        {
            // creates a Command 
            var cmd = context.Database.Connection.CreateCommand();
            cmd.CommandType = commandType;
            cmd.CommandText = sql;

            // adds all parameters
            foreach (var pr in parameters)
            {
                var p = cmd.CreateParameter();
                p.ParameterName = pr.Key;
                p.Value = pr.Value;
                cmd.Parameters.Add(p);
            }

            try
            {
                // executes
                context.Database.Connection.Open();
                var reader = cmd.ExecuteReader();

                // loop through all resultsets (considering that it's possible to have more than one)
                do
                {
                    // loads the DataTable (schema will be fetch automatically)
                    var tb = new DataTable();
                    tb.Load(reader);
                    result.Tables.Add(tb);

                } while (!reader.IsClosed);
            }
            finally
            {
                // closes the connection
                context.Database.Connection.Close();
            }
        }

        // returns the DataSet
        return result;
    }
1
Daniel Brilho