MiniProfiler - ProfiledDbDataAdapter - mvc-mini-profiler

Trying to get MiniProfiler to profile loading a DataTable via a Stored Proc
// Use a DbDataAdapter to return data from a SP using a DataTable
var sqlConnection = new SqlConnection(#"server=.\SQLEXPRESS;database=TestDB;Trusted_Connection=True;");
DbConnection connection = new StackExchange.Profiling.Data.ProfiledDbConnection(sqlConnection, MiniProfiler.Current);
var table = new DataTable();
DbDataAdapter dataAdapter = new SqlDataAdapter("GetCountries", sqlConnection);
ProfiledDbDataAdapter prdataAdapter = new ProfiledDbDataAdapter(dataAdapter, null);
// null reference exception here - SelectCommand is null
prdataAdapter.SelectCommand.CommandType = CommandType.StoredProcedure;
prdataAdapter.SelectCommand.Parameters.Add(new SqlParameter("#countryID", 2));
prdataAdapter.Fill(table);
ViewBag.table = table;
Problem: Null reference exception on SelectCommand
Please ignore lack of usings / disposing
I can successfully profile using ProfiledDbCommand to a SP:
// call a SP from DbCommand
var sqlConnection2 = new SqlConnection(#"server=.\SQLEXPRESS;database=TestDB;Trusted_Connection=True;");
DbConnection connection2 = new StackExchange.Profiling.Data.ProfiledDbConnection(sqlConnection2, MiniProfiler.Current);
if (connection2 != null)
{
using (connection2)
{
try
{
// Create the command.
DbCommand command = new SqlCommand();
ProfiledDbCommand prcommand = new ProfiledDbCommand(command, connection2, null);
prcommand.CommandType = CommandType.StoredProcedure;
prcommand.CommandText = "dbo.GetCountries";
prcommand.Parameters.Add(new SqlParameter("#countryID", 3));
prcommand.Connection = connection2;
//command.CommandText = "SELECT Name FROM Countries";
//command.CommandType = CommandType.Text;
// Open the connection.
connection2.Open();
// Retrieve the data.
DbDataReader reader = prcommand.ExecuteReader();
while (reader.Read())
{
var text = reader["Name"];
result += text + ", ";
}
}
catch (Exception ex)
{
}
}
}
Edit1:
This works:
// 2) SqlConnection, SqlDataAdapter.. dataAdapter command - works
var sqlConnection = new SqlConnection(#"server=.\SQLEXPRESS;database=TestDB;Trusted_Connection=True;");
var table = new DataTable();
//var dataAdapter = new SqlDataAdapter("GetCountries", sqlConnection);
var dataAdapter = new SqlDataAdapter("select * from countries", sqlConnection);
//dataAdapter.SelectCommand.CommandType = CommandType.StoredProcedure;
//dataAdapter.SelectCommand.Parameters.AddWithValue("#countryID", 2);
dataAdapter.Fill(table);
This doesn't DataTable.. but does with DataSet
var sqlConnection = new SqlConnection(#"server=.\SQLEXPRESS;database=TestDB;Trusted_Connection=True;");
DbConnection connection = new ProfiledDbConnection(sqlConnection, MiniProfiler.Current);
DbDataAdapter dataAdapter = new SqlDataAdapter("select * from countries", sqlConnection);
ProfiledDbDataAdapter prdataAdapter = new ProfiledDbDataAdapter(dataAdapter, null);
var table = new DataTable();
var dataset = new DataSet();
// Doesn't work
//prdataAdapter.Fill(table);
// Does work
prdataAdapter.Fill(dataset);

It turns out that though ProfiledDbDataAdapter inherited from DbDataAdapter, it did not override the default functionality of DbDataAdapter.Fill(DataTable), leading to the errors that you saw.
I fixed this in the MiniProfiler code. Fix is available in nuget, version 3.0.10-beta7 and higher.
I have tested this with your code from above and it works for me:
DbConnection connection =
new ProfiledDbConnection(sqlConnection, MiniProfiler.Current);
var sql = "select * from countries";
DbDataAdapter dataAdapter = new SqlDataAdapter(sql, sqlConnection);
ProfiledDbDataAdapter prdataAdapter = new ProfiledDbDataAdapter(dataAdapter);
var table = new DataTable();
dataAdapter.Fill(table); // this now works

Related

SQLDataAdapter and DataSet

I'm requested to work with a bit of code that uses an SqlDataAdapter, and I was wondering if this is the right approach.(I have looked at the documentation, but it's not totally clear in my mind)
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "SELECT * FROM MY_TABLE";
var Adapter = new SqlDataAdapter(cmd);
DataSet Result = new DataSet();
Adapter.Fill(Result);
Edit : think I found what was missing :
connectionString = help.Get_MyConnectionString();
Connection = new SqlConnection(connectionString);
Connection.Open();
Should work better with the connection open -.-"
Yes you need to open the connection. I would also wrap your SqlConnection and SqlDataAdapter in using blocks so that they are properly disposed.
using (var conn = new SqlConnection("YOUR CONNECTION STRING"))
{
conn.Open();
using (var adapter = new SqlDataAdapter(
"SELECT * FROM MY_TABLE", conn))
{
var result = new DataSet();
adapter.Fill(result);
}
}

SqlAdapter.Fill(DataSet) fills only first datatable returned by stored procedure in Xamarin

I try to fill my dataset with multiple tables using stored procedure on SQLServer. Code is simple:
var execProcedureString = "EXEC dbo.SomeProcedure ..."
var myDataSet = new DataSet();
using (var conn = new SqlConnection(connectionString))
{
using (var command = new SqlCommand(execProcedureString, conn))
{
using (var adapter = new SqlDataAdapter(command))
{
adapter.Fill(myDataSet);
}
}
}
But somehow Fill only creates (and fills) first table (not the others). It is not about procedure because it returns normal data. Am I missing something in the adapter?
I still don't know why Fill is not working. It worked before. There's walkaround (without need to specificate your datatables) but it envolves SqlDataReader
var execProcedureString = "EXEC dbo.SomeProcedure ..."
var myDataSet = new DataSet();
using (var conn = new SqlConnection(connectionString))
{
using (var command = new SqlCommand(execProcedureString, conn))
{
conn.Open();
using (var reader = new command.ExecuteReader())
{
while(!reader.IsClosed) //table.Load closes reader if it contains no more rows
{
var table = new DataTable();
myDataset.Tables.Add(table);
table.Load(reader)
}
}
}
}

Must declare the scalar variable "#historyId" exception

I have a working raw Sql command execution
using (var cmd = SqlUtils.CreateSqlCommand(cmdText, sqlConn))
{
cmd.Parameters.Add(new SqlParameter("historyId", SqlDbType.Int)).Value = AAverage.CashFlowRelevantHistoryId;
cmd.Parameters.Add(new SqlParameter("nodeId", SqlDbType.Int)).Value = AAverage.CashNodeId;
cmd.Parameters.Add(new SqlParameter("denomId", SqlDbType.Int)).Value = AAverage.DenominationId;
cmd.Parameters.Add(new SqlParameter("dayId", SqlDbType.Int)).Value = AAverage.CashFlowDayCategoryId;
cmd.Parameters.Add(new SqlParameter("hour", SqlDbType.Int)).Value = AAverage.Hour;
cmd.Parameters.Add(new SqlParameter("type", SqlDbType.Int)).Value = AAverage.ValueType;
cmd.Parameters.Add(new SqlParameter("average", SqlDbType.Real)).Value = AAverage.AverageDerivative;
using (var reader = cmd.ExecuteReader())
if (reader.HasRows && reader.Read())
{
IDataRecord record = (IDataRecord)reader;
AAverage.Id = record.GetInt32ByName("Id");
}
}
but if I've changed it to use SqlQuery method, I get the error in the subject:
StringBuilder cmdText = new StringBuilder();
cmdText.AppendLine("INSERT INTO CashFlowAverageDerivatives");
cmdText.AppendLine(" (CashFlowRelevantHistoryId, CashNodeId, DenominationId, CashFlowDayCategoryId, Hour, ValueType, AverageDerivative)");
cmdText.AppendLine("VALUES");
cmdText.AppendLine(" (#historyId, #nodeId, #denomId, #dayId, #hour, #type, #average)");
cmdText.AppendLine("SELECT Id FROM CashFlowAverageDerivatives WHERE ##ROWCOUNT > 0 and Id = scope_identity()");
AAverage.Id = ADbContext.Database.SqlQuery<int>(
cmdText.ToString(),
new SqlParameter("historyId", SqlDbType.Int).Value = AAverage.CashFlowRelevantHistoryId,
new SqlParameter("nodeId", SqlDbType.Int).Value = AAverage.CashNodeId,
new SqlParameter("denomId", SqlDbType.Int).Value = AAverage.DenominationId,
new SqlParameter("dayId", SqlDbType.Int).Value = AAverage.CashFlowDayCategoryId,
new SqlParameter("hour", SqlDbType.Int).Value = AAverage.Hour,
new SqlParameter("type", SqlDbType.Int).Value = AAverage.ValueType,
new SqlParameter("average", SqlDbType.Real).Value = AAverage.AverageDerivative
).First<int>();
and I have no idea why. If I tried to rename "historyId" in Sql text to something else, exception reports this new name. It seems like parameter definition was missing or misspelled, but list of parameters has been copy&pasted, VS IDE search command finds it, prefix "#" does not matter...
Sure I can live with my working version, but I'm learning EF and it tease me I'm not able to solve this
You were sending the sql parameter as value directly.
When you did this
new SqlParameter("historyId", SqlDbType.Int).Value = AAverage.CashFlowRelevantHistoryId
You actually sent a value of AAverage.CashFlowRelevantHistoryId, not a SqlParameter.
Try changing it with this and see if it works.
AAverage.Id = ADbContext.Database.SqlQuery<int>(
cmdText.ToString(),
new SqlParameter("historyId", AAverage.CashFlowRelevantHistoryId),
new SqlParameter("nodeId", AAverage.CashNodeId),
new SqlParameter("denomId", AAverage.DenominationId),
new SqlParameter("dayId", AAverage.CashFlowDayCategoryId),
new SqlParameter("hour", AAverage.Hour),
new SqlParameter("type", AAverage.ValueType),
new SqlParameter("average", AAverage.AverageDerivative)
).First<int>();
Or this
AAverage.Id = ADbContext.Database.SqlQuery<int>(
cmdText.ToString(),
new SqlParameter("historyId", SqlDbType.Int) { Value = AAverage.CashFlowRelevantHistoryId },
new SqlParameter("nodeId", SqlDbType.Int) { Value = AAverage.CashNodeId },
new SqlParameter("denomId", SqlDbType.Int) { Value = AAverage.DenominationId },
new SqlParameter("dayId", SqlDbType.Int) { Value = AAverage.CashFlowDayCategoryId },
new SqlParameter("hour", SqlDbType.Int) { Value = AAverage.Hour },
new SqlParameter("type", SqlDbType.Int) { Value = AAverage.ValueType },
new SqlParameter("average", SqlDbType.Real) { Value = AAverage.AverageDerivative }
).First<int>();

calling oracle stored procedure in c#

I am trying to call a oracle stored procedure in c# like this
OdbcDataAdapter da = new OdbcDataAdapter();
da.SelectCommand = new OdbcCommand();
da.SelectCommand.Connection = con;
da.SelectCommand.Connection.Open();
da.SelectCommand.CommandText = "KAMRAN.ATTN";
da.SelectCommand.CommandType = CommandType.StoredProcedure;
da.SelectCommand.ExecuteNonQuery();
da.SelectCommand.Connection.Close();
Label3.Text = "Attendance Posted Successfully";
But I am showing this error
ERROR [42000] [Oracle][ODBC][Ora]ORA-00900: invalid SQL statement
Please any One Can tell what exactly i am missing to call this procedure.plz help !
You could try to inverse the statements:
da.SelectCommand.CommandType = CommandType.StoredProcedure;
da.SelectCommand.CommandText = "KAMRAN.ATTN";
Also, maybe try to add:
da.SelectCommand.Parameters.Clear();
before
da.SelectCommand.CommandType = CommandType.StoredProcedure;
da.SelectCommand.CommandText = "KAMRAN.ATTN";
I think that you should also use a DataTable
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
Maybe that it should also be an Oracle Data Adapter:
OracleDataAdapter da = new OracleDataAdapter();
da.SelectCommand = new OracleCommand();
So you should have:
OracleDataAdapter da = new OracleDataAdapter();
da.SelectCommand = new OracleCommand();
da.SelectCommand.Connection = con;
da.SelectCommand.Connection.Open();
da.SelectCommand.Parameters.Clear();
da.SelectCommand.CommandType = CommandType.StoredProcedure;
da.SelectCommand.CommandText = "KAMRAN.ATTN";
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
da.SelectCommand.Connection.Close();
I hope this helps in any way.

Multiple result set from SQL Via LiNQ

I have a stored procedure as
pr___GetArchiveData
Select * from TABLE1
SELECT * FROM TABLE2
SELECT * FROM TABLE 3
I want to get this result set into a dataset. Or access the values of three select queries!!
I have a DBML file in which when i drag and drop the stored procedure generates a code as follows:-
global::System.Data.Linq.Mapping.FunctionAttribute(Name="dbo.pr___GetArchiveData")]
public ISingleResult<pr___GetArchiveDataResult> pr___GetArchiveData([global::System.Data.Linq.Mapping.ParameterAttribute(DbType="UniqueIdentifier")] System.Nullable<System.Guid> projectID)
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), projectID);
return ((ISingleResult<pr__Project_pr___GetArchiveData>)(result.ReturnValue));
}
In the code MVC3 Architecture + LINQ i have written a code to get the result set as follows :-
using (HBDataContext hb = new HBDataContext())
{
System.Data.DataSet ds = new System.Data.DataSet();
String connString = connString;
var conn = new System.Data.SqlClient.SqlConnection(connString);
var cmd = conn.CreateCommand();
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "pr__GetArchiveData";
cmd.Connection.Open();
var mReader = cmd.ExecuteReader(System.Data.CommandBehavior.SequentialAccess);
//var reader = cmd.ExecuteReader();
//using (System.Data.SqlClient.SqlDataReader mReader = cmd.ExecuteReader())
//{
// while (mReader.Read())
//{
// mReader.Read();
var tbl1 = hb.Translate<tbl1 >(mReader).ToList();
// mReader = cmd.ExecuteReader();
mReader.NextResult();
var tbl2 = hb.Translate<tbl2 >(mReader).ToList();
mReader.NextResult();
var tbl3 = hb.Translate<tbl3>(mReader).ToList();
// }
// }
}
But while running it throws error as -
"Invalid attempt to call NextResult when reader is closed."
I am not sure where i am wrong!!
I have tried using it as while
(mReader.Read())
Kindly suggest!!!!
The code gen for ISingleResult won't provide multiple result sets
Try adding your own IMultipleResults wrapper - see the tutorial in http://blogs.msdn.com/b/dditweb/archive/2008/05/06/linq-to-sql-and-multiple-result-sets-in-stored-procedures.aspx
In .dbml file for the stored procedure the code will be like
[global::System.Data.Linq.Mapping.FunctionAttribute(Name="dbo.pr__Home_GetArchiveData")]
public ISingleResult<pr__Home_GetArchiveData> pr__Home_GetArchiveData([global::System.Data.Linq.Mapping.ParameterAttribute(Name="AlbumID", DbType="UniqueIdentifier")] System.Nullable<System.Guid> albumID)
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), albumID);
return ((ISingleResult<pr__Album_GetAlbumsFilesResult>)(result.ReturnValue));
}
Replace it with IMultipleResult as below `
[global::System.Data.Linq.Mapping.FunctionAttribute(Name = "dbo.pr__Home_GetArchiveData")]
[ResultType(typeof(tbl1))]
[ResultType(typeof(tbl2))]
[ResultType(typeof(tbl3))]
[ResultType(typeof(tbl4))]
public IMultipleResults pr__Home_GetArchiveData([global::System.Data.Linq.Mapping.ParameterAttribute(Name = "HOMEID", DbType = "UniqueIdentifier")] System.Nullable hOMEID)
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), hOMEID);
return ((IMultipleResults)result.ReturnValue);
}
in the code .
using (HBDataContext hb = new HBDataContext())
{
using (System.Data.Linq.IMultipleResults _results = hb.pr__Home_GetArchiveData(model.HomeID))
{
List<tbl1> _tbl1= _results.GetResult<tbl1>().ToList();
List<tbl2> _tbl2= _results.GetResult<tbl2>().ToList();
List<tbl3> _tbl3= _results.GetResult<tbl3>().ToList();
List<tbl4> _tbl4= _results.GetResult<tbl4>().ToList();}}
You will get the values of the Select queries from theStoredProcedure ...

Resources