Linq query in stored procedure result set Ado.Net - entity-framework

I have a stored procedure with multiple joins, pulling all the data into a resultset I.e in dataset, now I want to write a linq query over it. How can I do that?
I am expecting:
IEnumerable<SomeType> result;
[where I need to know how the Properties of SomeType are defined.]
This is what I have tried but it does not look efficient.
SqlCommand cmd = new SqlCommand("Select top 10 * from trade");
cmd.Connection = con;
if (con.State != ConnectionState.Open)
{
con.Open();
}
SqlDataReader dr = cmd.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(dr);
var result = dt.AsEnumerable();
string valresukir = string.Empty;
var sortResult = result.OrderBy(x => Convert.ToInt32(x["trade_num"]) > 12);
string valuedata = string.Empty;
foreach (var i in sortResult)
{
valuedata += i["trade_num"].ToString();
}

to can write linq query on data table like
var data= from dataRow in dt.AsEnumerable()
where dataRow.Field<int>("trade_num") > 12
select dataRow
if trade_num is integer . Take it as a example and add your conditions accordingly.
Hope it will help you.

Related

Executing stored procedures and getting the output

I am trying to read the size of my database, and I can do this in SQL Server - but how do I run the following code in Entity Framework and get the output?
USE Impro_V2
GO
sp_spaceused
GO
or
EXEC sp_helpdb N'Impro_V2';
Using context.Database.ExecuteSqlCommand I get a result of "-1". I am not even sure whether that is failed.
How do run code like that?
The answer is here:
How to know the physical size of the database in Entity Framework?
The code is simple:
var ef = new MyDbContext();
var sqlConn = ef.Database.Connection as SqlConnection;
var cmd = new SqlCommand("sp_spaceused")
{
CommandType = System.Data.CommandType.StoredProcedure,
Connection = sqlConn as SqlConnection
};
var adp = new SqlDataAdapter(cmd);
var dataset = new DataSet();
sqlConn.Open();
adp.Fill(dataset);
sqlConn.Close();
// example read
foreach (DataTable table in dataset.Tables)
{
foreach (DataRow row in table.Rows)
{
foreach (DataColumn col in table.Columns)
{
console.write(row[icol].tostring());
etc

Android SQLite not returning data for given search term

I am trying to build a search interface but the SQLite database returns nothing here is the code for search function
public List<DiaryModel> searchData(String srchTerm){
List<DiaryModel> data2=new ArrayList<>();
SQLiteDatabase db1 = this.getWritableDatabase();
String sql="SELECT * FROM "+DB_TABLE+" WHERE "+KEY_HEADING+" LIKE '"+srchTerm+"%'";
Cursor cursor2 =db1.rawQuery(sql,null);
cursor2.moveToFirst();
StringBuilder stringBuffer2;
stringBuffer2 = new StringBuilder();
DiaryModel diaryModel2;
while (cursor2.moveToNext()){
diaryModel2 = new DiaryModel();
String heading = cursor2.getString(cursor2.getColumnIndexOrThrow("heading"));
String desc = cursor2.getString(cursor2.getColumnIndexOrThrow("desc_"));
diaryModel2.setHeading(heading);
diaryModel2.setDesc(desc);
stringBuffer2.append(diaryModel2);
data2.add(diaryModel2);
}
return data2;
}
but when I print everything the Database returns data, here is the code for get Data used for printing data present in Database
public List<DiaryModel> getdata(){
List<DiaryModel> data=new ArrayList<>();
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor =db.rawQuery("SELECT * FROM diary_db", null);
cursor.moveToFirst();
StringBuilder stringBuffer = new StringBuilder();
DiaryModel diaryModel;
while (cursor.moveToNext()){
diaryModel = new DiaryModel();
String heading = cursor.getString(cursor.getColumnIndexOrThrow(KEY_HEADING));
String desc = cursor.getString(cursor.getColumnIndexOrThrow(KEY_DESC));
diaryModel.setHeading(heading);
diaryModel.setDesc(desc);
stringBuffer.append(diaryModel);
data.add(diaryModel);
}
return data
}
The thing is only this SQL statement is working
SELECT * FROM diary_db
and if any condition is put nothing returns.
There is something that you are doing wrong in both methods:
cursor.moveToFirst();
and then:
while (cursor.moveToNext()){
.................
}
This way you miss the 1st row of the results, because after you move the cursor to the 1st row, you move once again to the next row.
So delete this:
cursor.moveToFirst();
from both methods.

Entity Framework Stored Procedure Call Significantly Slower

Any reason why I'm getting significantly lower performance using Entity Framework? Both versions of the code below are accomplishing the exact same goal.
The Excel document has 1700 records that are being inserted into a SQL Azure database.
Using Entity Framework Execution Time: 4:55
foreach (IXLRow row in wb.Worksheet(1).RowsUsed())
{
dbContext.InsertQuestion(row.Cell("B").Value.ToString().Trim(), row.Cell("A").Value.ToString().Trim(), row.Cell("C").Value.ToString().Trim(), row.Cell("D").Value.ToString().Trim(), null);
}
Non-Entity Framework Execution Time: 1:54
foreach (IXLRow row in wb.Worksheet(1).RowsUsed())
{
using (SqlCommand cmd = new SqlCommand("InsertQuestion", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#CategoryName", row.Cell("B").Value.ToString().Trim()));
cmd.Parameters.Add(new SqlParameter("#TypeName", row.Cell("A").Value.ToString().Trim()));
cmd.Parameters.Add(new SqlParameter("#Text", row.Cell("C").Value.ToString().Trim()));
cmd.Parameters.Add(new SqlParameter("#Answer", row.Cell("D").Value.ToString().Trim()));
cmd.ExecuteNonQuery();
}
}
First, create a data type on your database (like the database has VARCHAR and INT types you can create your own TYPE.)
CREATE TYPE SurveyAnswerType AS TABLE
(
CategoryName VARCHAR(255),
TypeName VARCHAR(255),
[Text] VARCHAR(255),
Answer VARCHAR(255)
)
GO
Second, use the new type as a parameter to a stored proc
CREATE PROCEDURE InsertSurveyAnswers
#Answers SurveyAnswerType READONLY
AS
INSERT INTO Answers
(CategoryName, TypeName, [Text], Answer)
SELECT CategoryName, TypeName, [Text], Answer
FROM #Answers
GO
Third, call the stored proc from C# code by loading a table that looks like your new type:
DataTable tAnswers = new DataTable();
tAnswers.Columns.Add("CategoryName", typeof(String));
tAnswers.Columns.Add("TypeName", typeof(String));
tAnswers.Columns.Add("Text", typeof(String));
tAnswers.Columns.Add("Answer", typeof(String));
var rows = wb.Worksheet(1).RowsUsed();
var totalRows = rows.Count();
int index = 0;
int bufferSize;
using (SqlCommand cmd = new SqlCommand("InsertAnswers", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#SurveyAnswerType",
SqlDbType.Structured));
while(index < totalRows)
{
int bufferSize = Math.Min(200, totalRows - index);
foreach (index = index; index < bufferSize; index++)
{
var newRow = tAnswerstAnswers.NewRow();
newRow[0] = rows[index].Cell("A").Value.ToString().Trim();
newRow[1] = row[index].Cell("B").Value.ToString().Trim();
newRow[2] = row[index].Cell("C").Value.ToString().Trim();
newRow[3] = row[index].Cell("D").Value.ToString().Trim();
tAnswerstAnswers.AddRow(newRow);
}
cmd.Parameters["#SurveyAnswerType"].Value = tAnswers;
cmd.ExecuteNonQuery();
}
}
Things to note:
The SqlParameter used SqlDbType.Structured.
The connection is only opened and closed / destroyed once, not once for
each row.
You should play with the buffer size to see what is the best size.
You will have to come up with your own entity framework version of
this - but I suspect that there is overhead with each call that you
will minimize with this pattern.

Returning a DataTable using Entity Framework ExecuteStoreQuery

I am working with a system that has many stored procedures that need to be displayed. Creating entities for each of my objects is not practical.
Is it possible and how would I return a DataTable using ExecuteStoreQuery ?
public ObjectResult<DataTable> MethodName(string fileSetName) {
using (var dataContext = new DataContext(_connectionString))
{
var returnDataTable = ((IObjectContextAdapter)dataContext).ObjectContext.ExecuteStoreQuery<DataTable>("SP_NAME","SP_PARAM");
return returnDataTable;
}
Yes it's possible, but it should be used for just dynamic result-set or raw SQL.
public DataTable ExecuteStoreQuery(string commandText, params Object[] parameters)
{
DataTable retVal = new DataTable();
retVal = context.ExecuteStoreQuery<DataTable>(commandText, parameters).FirstOrDefault();
return retVal;
}
Edit: It's better to use classical ADO.NET to get the data model rather than using Entity Framework because most probably you cannot use DataTable even if you can run the method: context.ExecuteStoreQuery<DataTable>(commandText, parameters).FirstOrDefault();
ADO.NET Example:
public DataSet GetResultReport(int questionId)
{
DataSet retVal = new DataSet();
EntityConnection entityConn = (EntityConnection)context.Connection;
SqlConnection sqlConn = (SqlConnection)entityConn.StoreConnection;
SqlCommand cmdReport = new SqlCommand([YourSpName], sqlConn);
SqlDataAdapter daReport = new SqlDataAdapter(cmdReport);
using (cmdReport)
{
SqlParameter questionIdPrm = new SqlParameter("QuestionId", questionId);
cmdReport.CommandType = CommandType.StoredProcedure;
cmdReport.Parameters.Add(questionIdPrm);
daReport.Fill(retVal);
}
return retVal;
}
No, I don't think that'll work - Entity Framework is geared towards returning entities and isn't meant to return DataTable objects.
If you need DataTable objects, use straight ADO.NET instead.
This method uses the connection string from the entity framework to establish an ADO.NET connection, to a MySQL database in this example.
using MySql.Data.MySqlClient;
public DataSet GetReportSummary( int RecordID )
{
var context = new catalogEntities();
DataSet ds = new DataSet();
using ( MySqlConnection connection = new MySqlConnection( context.Database.Connection.ConnectionString ) )
{
using ( MySqlCommand cmd = new MySqlCommand( "ReportSummary", connection ) )
{
MySqlDataAdapter adapter = new MySqlDataAdapter( cmd );
adapter.SelectCommand.CommandType = CommandType.StoredProcedure;
adapter.SelectCommand.Parameters.Add( new MySqlParameter( "#ID", RecordID ) );
adapter.Fill( ds );
}
}
return ds;
}
Yes it can easily be done like this:
var table = new DataTable();
using (var ctx = new SomeContext())
{
var cmd = ctx.Database.Connection.CreateCommand();
cmd.CommandText = "Select Col1, Col2 from SomeTable";
cmd.Connection.Open();
table.Load(cmd.ExecuteReader());
}
By the rule, you shouldn't use a DataSet inside a EF application. But, if you really need to (for instance, to feed a report), that solution should work (it's EF 6 code):
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;
}
In my Entity Framework based solution I need to replace one of my Linq queries with sql - for efficiency reasons.
Also I want my results in a DataTable from one stored procedure so that I could create a table value parameter to pass into a second stored procedure. So:
I'm using sql
I don't want a DataSet
Iterating an IEnumerable probably isn't going to cut it - for efficiency reasons
Also, I am using EF6, so I would prefer DbContext.SqlQuery over ObjectContext.ExecuteStoreQuery as the original poster requested.
However, I found that this just didn't work:
_Context.Database.SqlQuery<DataTable>(sql, parameters).FirstOrDefault();
This is my solution. It returns a DataTable that is fetched using an ADO.NET SqlDataReader - which I believe is faster than a SqlDataAdapter on read-only data. It doesn't strictly answer the question because it uses ADO.Net, but it shows how to do that after getting a hold of the connection from the DbContext
protected DataTable GetDataTable(string sql, params object[] parameters)
{
//didn't work - table had no columns or rows
//return Context.Database.SqlQuery<DataTable>(sql, parameters).FirstOrDefault();
DataTable result = new DataTable();
SqlConnection conn = Context.Database.Connection as SqlConnection;
if(conn == null)
{
throw new InvalidCastException("SqlConnection is invalid for this database");
}
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.AddRange(parameters);
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
result.Load(reader);
}
return result;
}
}
The easiest way to return a DataTable using the EntityFramework is to do the following:
MetaTable metaTable = Global.DefaultModel.GetTable("Your EntitySetName");
For example:
MetaTable metaTable = Global.DefaultModel.GetTable("Employees");
Maybe your stored procedure could return a complex type?
http://blogs.msdn.com/b/somasegar/archive/2010/01/11/entity-framework-in-net-4.aspx

MARS vs NextResult

I rehydrate my business objects by collecting data from multiple tables, e.g.,
SELECT * FROM CaDataTable;
SELECT * FROM NyDataTable;
SELECT * FROM WaDataTable;
and so on...
(C# 3.5, SQL Server 2005)
I have been using batches:
void BatchReader()
{
string sql = "Select * From CaDataTable" +
"Select * From NyDataTable" +
"Select * From WaDataTable";
string connectionString = GetConnectionString();
using (SqlConnection conn = new SqlConnection(connectionString)) {
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
using (SqlDataReader reader = cmd.ExecuteReader()) {
do {
while (reader.Read()) {
ReadRecords(reader);
}
} while (reader.NextResult());
}
}
}
I've also used multiple commands against the same connection:
void MultipleCommandReader()
{
string connectionString = GetConnectionString();
string sql;
SqlCommand cmd;
using (SqlConnection conn = new SqlConnection(connectionString)) {
conn.Open();
sql = "Select * From CaDataTable";
cmd = new SqlCommand(sql, conn);
using (SqlDataReader reader = cmd.ExecuteReader()) {
while (reader.Read()) {
ReadRecords(reader);
}
}
sql = "Select * From NyDataTable";
cmd = new SqlCommand(sql, conn);
using (SqlDataReader reader = cmd.ExecuteReader()) {
while (reader.Read()) {
ReadRecords(reader);
}
}
sql = "Select * From WaDataTable";
cmd = new SqlCommand(sql, conn);
using (SqlDataReader reader = cmd.ExecuteReader()) {
while (reader.Read()) {
ReadRecords(reader);
}
}
}
}
Is one of these techniques significantly better than the other?
Also, would there be a gain if I use MARS on the second method? In other words, is it as simple as setting MultipleActiveResultSets=True in the connection string and reaping a big benefit?
If the data structure is the same in each table, I would do:
Select *, 'Ca' Source From CaDataTable
union all
Select *, 'Ny' Source From NyDataTable
union all
Select *, 'Wa' Source From WaDataTable
Without actually timing the two versions against one another, you can only speculate....
I hope bet that version 1 (BatchReader) will be faster, since you only get one round-trip to the database. Version 2 requires three distinct round-trips - one each for every query you execute.
But again: you can only really tell if you measure.
Marc
Oh, PS: of course in a real-life scenario it would also help so limit the columns returned, e.g. don't use SELECT * but instead use SELECT (list of fields) and keep that list of fields as short as possible.