How to build correct query notification? - asp.net

could someone please help me, I'm trying to set up alerts with the total amount of records for some tables that I want. In this example, I'm just trying to return COUNT as a result of one of the tables to say how many records don't have schedules for the customer, however with all these exceptions
Creating a Query for Notification
,I couldn't think of a solution for my case.
SELECT COUNT(A.CODREF)QTDEAGENDSEMAGENDA FROM REGISTROS A INNER JOIN ATENDENTES U ON U.CODUSUARIO = A.CODUSUARIO WHERE A.CODUSUARIO = 11 AND A.STATUS IS NULL AND A.CODREF NOT IN ( SELECT CODREF FROM RETORNOS WHERE CODDIALOGO IS NULL AND AGEND_INTERNO IS NULL ) AND DATEDIFF(DAY, A.INICIO, GETDATE())> 11
All the queries I'm going to assemble will look like this in the example. I had thought of creating a view.
Calling my view:
SELECT QTDEAGENDSEMAGENDA FROM ALERTS
then the query would be simple and it would work, but I saw that it is also on the list not to be used.
This is my code and does not work with this query that I set up or with the View
public class NotificationHub : Hub
{
string qtdeAgendSemAgenda = string.Empty;
[HubMethodName("sendNotifications")]
public string SendNotifications()
{
using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
string query = #"SELECT COUNT(A.CODREF)QTDEAGENDSEMAGENDA FROM REGISTROS A INNER JOIN ATENDENTES U ON U.CODUSUARIO = A.CODUSUARIO WHERE A.CODUSUARIO = 11 AND A.STATUS IS NULL AND A.CODREF NOT IN ( SELECT CODREF FROM RETORNOS WHERE CODDIALOGO IS NULL AND AGEND_INTERNO IS NULL ) AND DATEDIFF(DAY, A.INICIO, GETDATE())> 11";
connection.Open();
using (SqlCommand command = new SqlCommand(query, connection))
{
command.Notification = null;
DataTable dt = new DataTable();
SqlDependency dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
if (connection.State == ConnectionState.Closed)
connection.Open();
var reader = command.ExecuteReader();
dt.Load(reader);
if (dt.Rows.Count > 0)
{
qtdeAgendSemAgenda = (dt.Rows[0]["QTDEAGENDSEMAGENDA"].ToString());
}
}
}
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
return Tratar.String(context.Clients.All.RecieveNotification(qtdeAgendSemAgenda));
}

Related

How to execute stored procedure in EF7 beta8?

I'm trying to run stored procedure in EF7 beta8 to return me a specific data. I'm trying to do it via FromSQL command, but not sure if this is right command.
strSQL = wt.DataSource.StoredProc;
foreach (var p in prms)
{
strSQL = strSQL + " #" + p.Name + " = '" + p.Value + "',";
}
strSQL = strSQL.Remove(strSQL.Length - 1); //removes last comma
var test = _dbContext.Widgets.FromSql("EXEC " + strSQL).ToList();
var test2 = _dbContext.Widgets.FromSql("SELECT * FROM Widgets").ToList();
Where test 2 works and returns data correctly, test1 is returning error:
The required column 'Id' was not present in the results of a 'FromSql' operation.
I'm assuming that the data I'm returning is not part of the model. If that's the case, how can I execute stored procedure and return the raw data to List or to DataTable?
EDIT:
I'm trying with SQLCommand:
var connection = (SqlConnection)_dbContext.Database.GetDbConnection();
var command = connection.CreateCommand();
command.CommandType = CommandType.StoredProcedure;
command.CommandText = strSQL;
foreach(var p in prms)
{
command.Parameters.Add("#" + p.Name, p.Value);
}
connection.Open();
var test = command.ExecuteNonQuery();
connection.Close();
Bus still no luck:
No mapping exists from object type Newtonsoft.Json.Linq.JValue to a known managed provider native type.
Is there any other way to execute stored procedure without mapping the entity?
You should be able to use normal SqlCommand and ExecuteReader method to get data from a stored procedure.
Quick sample.
This code executes a stored procedure called GetWidgets which expects 2 parameters, #name and #categoryId and returns a result set which has 2 columns, Id and Name. We are reading the value from the DataReader and creating an object of WidgetDto and appending to a list of WidgetDto.
Your WidgetDto is a simple POCO
public class WidgetDto
{
public int Id {set;get;}
public string Name {set;get;}
}
And the code to execute stored proc is
private List<WidgetDto> GetWidgets(d)
{
var catId= 1;
var name ="test"
//The above values are hard coded for demo. you may replace it
// with whatever your stored proc is expecting.
var list = new List<WidgetDto>();
const string sqlQry = "exec GetWidgets #name,#categoryId";
using (var db = new StudentsEntities())
{
using (var con = (SqlConnection) db.Database.Connection)
{
using (var cmd = new SqlCommand(sqlQry, con))
{
cmd.Parameters.AddWithValue("#name", name);
cmd.Parameters.AddWithValue("#categoryId", catId);
con.Open();
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
var s = new GoodVm();
s.Id = reader.GetInt32(reader.GetOrdinal("Id"));
s.Name = reader.GetString(reader.GetOrdinal("Name"));
list.Add(s);
}
}
}
}
}
return list;
}
In this example, I am using db.DataBase.Connection (Available in ED 6.13 version) property of my DbContext to build the connection. You can build your connection from the legacy way also by using the connection string.

ASP.NET select * from table and save them in variable

I'am new in asp.net. I want to select values from database table.
If it was PHP I would do it like following code.
$query = mysql_query(" SELECT * FROM Table WHERE id = ".$d." ");
while($row = mysql_fetch_array($query))
{
$firstname = $row['firstname'];
$lastname = $row['lastname'];
}
How would I do if it was in asp.net if I use SqlConnection ...and SqlCommand or maybe if there is some beter Connections.... Thank you in advance guys....
//Create a command, using a parameter
var command = new SqlCommand("select firstname, lastname from table where id=#id");
command.Parameters.AddWithValue("id", id);
DataTable dt = new DataTable();
//use a using statement to ensure the connection gets disposed properly
using(var connection = new SqlConnection("connectionstring"))
{
command.Connection = connection;
connection.Open();
//execute the command and load the results in a data table
dt.Load(command.ExecuteReader());
}
//loop through the results of the data table
foreach(var row in dt.Rows)
{
var firstname = row.Field<string>("firstname");
var lastname = row.Field<string>("lastname");
//do something with firstname and lastname
}
This isn't a direct translation since I'm storing the values in a DataTable, but that is usually better than leaving the data connection open.

Nested Queries In ASP.Net Without Async

I have the following code and basically I want it go step by step using the If statements. When I run this however I get this asp error: "This command requires an asynchronous connection. Set "Asynchronous Processing=true" in the connection string."
On this bit of code:
"addToTable.BeginExecuteReader();"
However I do not want it to by async I want it to run the subsequent queries only if the previous conditions are met.
Full code is below:
string dataset="";
if (System.Web.HttpContext.Current.Session["user"] != null)
{
if (name != null && carId != null)
{
using (SqlConnection con = new SqlConnection(st))
{
string getCar = "SELECT * FROM [Car] WHERE CarId = #carId";
SqlCommand cmd = new SqlCommand(getCarData, con);
cmd.Parameters.AddWithValue("#carId", carId);
using (cmd)
{
con.Open();
SqlDataReader data = cmd.ExecuteReader();
if (data.HasRows)
{
while (data.Read())
{
if (data["available"].ToString() == "0")
{
data.Close();
SqlCommand getParts = new SqlCommand("SELECT * FROM [CarCustomer] WHERE UserId = #UserId AND car=#carId", con);
getParts.Parameters.AddWithValue("#userId", System.Web.HttpContext.Current.Session["userId"]);
getParts.Parameters.AddWithValue("#carId", carId);
SqlDataReader grabRows = getParts.ExecuteReader();
if (grabRows.HasRows)
{
grabRows.Close();
SqlCommand updateTable = new SqlCommand("UPDATE [Table1] SET salesAmount=5 WHERE UserId=1", con);
updateTable.BeginExecuteReader();
}
else
{
grabRows.Close();
SqlCommand addToTable = new SqlCommand("INSERT INTO [Table1] (salesAmount) Values("1")", con);
addToTable.BeginExecuteReader();
}
dataset="good"
}
}
}
}
}
}
}
return dataset;
Instead of BeginExecuteReader command use SqlCommand.ExecuteNonQuery , because ExecuteNonQuery is used to perform query like insert,update and delete where as for Gettting data Read method is used.
one more thing BeginExecuteReadermethod is used to perfrom asncy read operation so if you dont want that than just use ExecuteReadermethod to get data.
Read SqlCommand.ExecuteNonQuery -
You can use the ExecuteNonQuery to perform catalog operations (for example, querying the structure of a database or creating database objects such as tables), or to change the data in a database without using a DataSet by executing UPDATE, INSERT, or DELETE statements.

Populate web form edit page C# ASP.NET

I am trying to select a single row on a gridview and have that selection take me to a separate edit page with the data populated. I have the idea of using a session variable to hold the row id and then retrieving the data on page load and populating the text boxes. My question is whether or not this is the best method to go about doing this? I would prefer to not use the inline edit option in gridview as I have too many columns that would require scrolling horizontally. Here is my page load method using the session variable:
if (Session["editID"] != null)
{
dbCRUD db = new dbCRUD();
Recipe editRecipe = new Recipe();
var id = Convert.ToInt32(Session["editID"]);
Session.Remove("editID");
editRecipe = db.SelectRecord(id);
addName.Text = editRecipe.Name;
}
Here is the SelectRecord method that is used to retrieve the row:
public Recipe SelectRecord(int id)
{
Recipe returnedResult = new Recipe();
var dbConn = new SqlConnection(connString);
var dbCommand = new SqlCommand("dbo.selectRecipe", dbConn);
dbCommand.CommandType = CommandType.StoredProcedure;
dbCommand.Parameters.Add("#ID", SqlDbType.Int).Value = id;
dbConn.Open();
SqlDataReader reader = dbCommand.ExecuteReader();
while (reader.HasRows)
{
while (reader.Read())
{
returnedResult.Name = reader["Name"].ToString();
}
}
dbConn.Close();
return returnedResult;
}
I'm probably not utilizing the SQLDataReader appropriately, but my result is no data in the reader therefore no returned data when calling the method. Any help is appreciated - thanks in advance!
Few things you should be aware of here:
1.
You should use while (reader.HasRows) in case your stored procedure returns multiple resultsets. In that case you have to iterate through the result sets. See Retrieving Data Using a DataReader. So, if selectRecipe returns multiple resultsets (I am assuming this is not the case), change your code to this:
while (reader.HasRows)
{
while (reader.Read())
{
returnedResult.Name = reader["Name"].ToString();
}
reader.NextResult();
}
2.If selectRecipe returns single result set, change the while loop to if(){}:
if(reader.HasRows)
{
while (reader.Read())
{
returnedResult.Name = reader["Name"].ToString();
}
}
3. I would probably use using to manage the connection better (using Statement) :
public Recipe SelectRecord(int id)
{
Recipe returnedResult = new Recipe();
using (SqlConnection dbConn = new SqlConnection(connString))
{
var dbCommand = new SqlCommand("dbo.selectRecipe", dbConn);
dbCommand.CommandType = CommandType.StoredProcedure;
dbCommand.Parameters.AddWithValue("#ID", id);
dbConn.Open();
SqlDataReader reader = dbCommand.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
returnedResult.Name = reader["Name"].ToString();
}
}
reader.Close();
}
return returnedResult;
}

How do I fill a DataTable using DataReader

I want to fill DataTable using DataReader.
I have created object like this
SqlDataReader dr = cmd.ExecuteReader();
if(dr.HasRows)
{
}
If all you want is a ReadOnly DataTable for reporting or web, try this:
conn = new SqlConnection(connString);
string query = "SELECT * FROM Customers";
SqlCommand cmd = new SqlCommand(query, conn);
conn.Open();
SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
DataTable dt = new DataTable();
dt.Load(dr);
Credit where it's due: http://www.dotnetcurry.com/showarticle.aspx?ID=143
DataTable.load() can be used for a generic approach.
do {
var table = new DataTable();
table.Load(reader);
dataset.Tables.Add(table);
} while(!reader.IsClosed);
You can get the Schema Table from your SqlDataReader dr to get the column names, save the names to a List<string> and add them as columns on a new DataTable, then fill that DataTable using indexing on dr with the names from the list:
DataSet ds = new DataSet();
DataTable dtSchema = dr.GetSchemaTable();
DataTable dt = new DataTable();
List<DataColumn> listCols = new List<DataColumn>();
List<DataColumn> listTypes = new List<DataColumn>();
if (dtSchema != null)
{
foreach (DataRow drow in dtSchema.Rows)
{
string columnName = System.Convert.ToString(drow["ColumnName"]);
DataColumn column = new DataColumn(columnName, (Type)(drow["DataType"]));
listCols.Add(column);
listTypes.Add(drow["DataType"].ToString()); // necessary in order to record nulls
dt.Columns.Add(column);
}
}
// Read rows from DataReader and populate the DataTable
if (dr.HasRows)
{
while (dr.Read())
{
DataRow dataRow = dt.NewRow();
for (int i = 0; i < listCols.Count; i++)
{
if (!dr.IsDBNull[i])
{
// If your query will go against a table with null CLOB fields
// and that column is the 5th column...
if (strSQL == "SELECT * FROM TableWithNullCLOBField" && i == 4)
dataRow[((DataColumn)listCols[i])] = dr.GetOracleClob(i).Value;
// If you might have decimal values of null...
// I found dr.GetOracleDecimal(i) and dr.GetDecimal(i) do not work
else if (listTypes[i] == System.Decimal)
dataRow[((DataColumn)listCols[i])] = dr.GetFloat(i);
else
dataRow[((DataColumn)listCols[i])] = dr[i]; // <-- gets index on dr
}
else // value was null
{
byte[] nullArray = new byte[0];
switch (listTypes[i])
{
case "System.String":
dataRow[((DataColumn)listCols[i])] = String.Empty;
break;
case "System.Decimal":
case "System.Int16": // Boolean
case "System.Int32": // Number
dataRow[((DataColumn)listCols[i])] = 0;
break;
case "System.DateTime":
dataRow[((DataColumn)listCols[i])] = DBNull.Value;
break;
case "System.Byte[]": // Blob
dataRow[((DataColumn)listCols[i])] = nullArray;
break;
default:
dataRow[((DataColumn)listCols[i])] = String.Empty;
break;
}
}
}
dt.Rows.Add(dataRow);
}
ds.Tables.Add(dt);
}
// Put this after everything is closed
if (ds.Tables.Count > 0)
return ds.Tables[0]; // there should only be one table if we got results
else
return null;
Obviously you'd need your try...catch...finally block around it all to handle exceptions and disposing your connection, and use the last condition after the finally. I found this helpful in order to handle finding out when I had results or not, and avoided issues with dt.Load(dr) that was failing when there were no results. ds.Fill(adapter) wasn't much better, as it failed when I tried to grab a table of 97 columns and about 80 rows with SELECT * FROM MyTable. Only the code above managed to work in all scenarios, for me.
Originally posted on Populate data table from data reader by sarathkumar. I provided the summary, condensed it, added the null checks and assigning if it's a null value, and added the table to a DataSet and added the DataSet condition at the end.
NOTE: For those using OracleDataReader, I found out that you can experience an error if you have an NCLOB or CLOB field that is null in the table/results set that you are reading. I found if I checked for that column by looking at the index i and did dr.GetOracleClob(i) instead of dr[i], I stopped getting the exception. See answer at EF + ODP.NET + CLOB = Value Cannot be Null - Parameter name: byteArray? and I added this condition in the code above when if (!dr.IsDBNull[i]). Similarly, if you have a null Decimal field, I had to check it with dr.GetFloat(i);, since neither dr.GetOracleDecimal(i); and dr.GetDecimal(i); seemed to correctly accommodate for a null value.
To fill a DataSet, you can use something like:
var da = new SqlDataAdapter();
da.SelectCommand = cmd; // your SqlCommand object
var ds = new DataSet();
da.Fill(ds);

Resources