エンティティフレームワークを使用しています。アプリケーションには、ストアドプロシージャを使用する必要がある特定の状況が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.
}
どうもありがとう。解決しました。解決策は次のとおりです。
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;
}
この例では、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;
});
このソリューションは、シンプルで非常に高速で使いやすいです。
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()
);
}
汎用パラメーター(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;
}