I have the following Webservice and SQL-Query:
public class DIENSTLEISTUNG
{
public string DienstleistungName { get; set; }
public string DienstleistungArtBezeichnung { get; set; }
}
internal static List<DIENSTLEISTUNG> Dienstleistung(string RAUM_ID)
{
List<DIENSTLEISTUNG> BestuhlungObject = new List<DIENSTLEISTUNG>();
using (SqlConnection con = new SqlConnection(#"Data Source=Localhost\SQLEXPRESS;Initial Catalog=BOOK-IT-V2;Integrated Security=true;"))
using (SqlCommand cmd = new SqlCommand(#"
SELECT
DISTINCT dl.NAME AS NAME, da.BEZEICHNUNG AS BEZEICHNUNG
FROM RAUM r
RIGHT JOIN DIENSTLEISTUNG_Raum bs ON bs.RAUM_ID = (" + Room_ID + ")
RIGHT JOIN DIENSTLEISTUNG ba ON bs.DIENSTLEISTUNG_ID = ba.ID
RIGHT JOIN DIENSTLEISTUNGSART da ON ba.DIENSTLEISTUNGSART_ID = da.ID
RIGHT JOIN DIENSTLEISTER dl ON da.DIENSTLEISTER_ID = dl.ID", con))
{
con.Open();
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
if (rdr["NAME"] != DBNull.Value && rdr["BEZEICHNUNG"] != DBNull.Value)
{
BestuhlungObject.Add(new DIENSTLEISTUNG()
{
DienstleistungName = rdr["NAME"].ToString(),
DienstleistungArtBezeichnung = rdr["BEZEICHNUNG"].ToString()
});
}
}
}
}
return BestuhlungObject;
}
}
}
This Webservice is working like charm. I can send one Room_ID = 219 and get the expected output. My Question is, how can i send more then one Room_ID seperated by comma. For Example: Room_ID = 219, 220, 221
Can someone please help me with that?
Thanks in advance
See T-SQL stored procedure that accepts multiple Id values
One of many ways (MS SQL 2005+), if you can pass parameters as xml:
var sql =
#"SET ARITHABORT ON;
SELECT ...
RIGHT JOIN DIENSTLEISTUNG_Raum bs ON bs.RAUM_ID IN
(
SELECT tbl.col.value('.', 'varchar(20)')
FROM #xml.nodes('id') as tbl(col)
) ...";
SqlCommand cmd = new SqlCommand(sql, connection);
cmd.Parameters.Add("#xml", SqlDbType.Xml).Value = "<id>111</id><id>222</id><id>333</id>";
Or using LIKE if you can pass parameters as ,aaa,bbb,ccc, (note the order of LIKE arguments to avoid an injection)
var sql =
#"SELECT ...
RIGHT JOIN DIENSTLEISTUNG_Raum bs ON #ids LIKE '%,' + bs.RAUM_ID + ',%'
...";
SqlCommand cmd = new SqlCommand(sql, connection);
cmd.Parameters.Add("#ids", SqlDbType.VarChar).Value = ",111,222,333,";
Related
I have parameterized stored procedure (tested and works) in mysql.
I wanted to replace my long select statement with stored procedure in my code.
With select statement it worked but now I am not able to run it with sp (commented string req).
My stored procedure:
CREATE DEFINER=`root`#`%` PROCEDURE `GetProjectVM`(
IN projectName NVARCHAR(255)
)
BEGIN
select VirtualMachines.Name,
VirtualMachines.IpAddress,
VirtualMachines.DiskSize,
VirtualMachines.CPU,
VirtualMachines.Ram,
VirtualMachines.ImageUrl,
VirtualMachines.Role,
Hypervisors.Name as Hypervisor,
Managements.Netmask,
Managements.Gateway from VirtualMachines inner join Projects
on Projects.id = VirtualMachines.ProjectId inner join Hypervisors
on Hypervisors.HypervisorId = VirtualMachines.HypervisorId inner join Managements
on VirtualMachines.ManagementId = Managements.Id
where Projects.Name = projectName;
END
My code looks like:
private string _dbUrl;
private MySqlConnection _cnn;
public Dbmanagement(string dbUrl)
{
this._dbUrl = dbUrl;
this._cnn = new MySqlConnection(this._dbUrl);
}
private MySqlDataReader ExecuteMysqlCommand(string cmd)
{
_cnn.Open();
var result = new MySqlCommand(cmd, _cnn);
return result.ExecuteReader();
}
public IEnumerable<VM> GetProjectVM(string projectName)
{
var vmList = new List<VM>();
//string req =
// $"select VirtualMachines.Name,VirtualMachines.IpAddress,VirtualMachines.DiskSize,VirtualMachines.CPU,VirtualMachines.Ram,VirtualMachines.ImageUrl,VirtualMachines.Role,Hypervisors.Name as Hypervisor,Managements.Netmask,Managements.Gateway from VirtualMachines inner join Projects on Projects.id = VirtualMachines.ProjectId inner join Hypervisors on Hypervisors.HypervisorId = VirtualMachines.HypervisorId inner join Managements on VirtualMachines.ManagementId = Managements.Id where Projects.Name = \"{projectName}\" ;";
MySqlCommand cmd = new MySqlCommand("GetProjectVM", _cnn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#projectName", projectName);
var req = cmd;
var rd = ExecuteMysqlCommand(req.ToString());
while (rd.Read())
{
vmList.Add(new VM(rd));
}
_cnn.Close();
return vmList;
}
The problem - or at least the first problem - is how you're executing the command.
Calling ToString on a MySqlCommand is very unlikely to be able to convey all the relevant information. You're losing parameterization, command type etc.
Change this:
var req = cmd;
var rd = ExecuteMysqlCommand(req.ToString());
to
_cnn.Open();
var rd = req.ExecuteReader();
I'd also suggest not having a single MySqlConnection, but just constructing one when you need to, and letting the connection pool manage making that efficient. So something like:
using (var connection = new MySqlConnection(_dbUrl))
{
connection.Open();
using (var cmd = new MySqlCommand("GetProjectVM", connection))
{
cmd.CommandType = CommandType.StoredProcedure;
// Avoid AddWithValue where possible, to avoid conversion issues.
cmd.Parameters.Add("#projectName", MySqlDbType. VarChar).Value = projectName;
using (var reader = cmd.ExecuteReader())
{
var list = new List<VM>();
while (reader.Read())
{
list.Add(new VM(reader));
}
return list;
}
}
}
I want to retrive data from two differentables in my mysql data base so i created one connection and two readers, The second reader is not returning any results but the first reader is.
public List<BlogContentItemClass> BCITLIST = new List<BlogContentItemClass>();
// GET: api/BlogContents
[HttpGet]
public List<BlogContentItemClass> Get(string id)
{
string sqlstring = "server=; port= ; user id =;Password=;Database=;";
MySqlConnection conn = new MySqlConnection(sqlstring);
try
{
conn.Open();
}
catch (MySqlException ex)
{
throw ex;
}
string Query = "SELECT * FROM test.blogtable where `id` = '" + id + "' ";
MySqlCommand cmd = new MySqlCommand(Query, conn);
MySqlDataReader MSQLRD = cmd.ExecuteReader();
BlogContentItemClass BCIT = new BlogContentItemClass();
Label BLOGID = new Label();
if (MSQLRD.HasRows)
{
while (MSQLRD.Read())
{
string TC = (MSQLRD["Topic"].ToString());
string CT = (MSQLRD["Category"].ToString());
string SM = (MSQLRD["Summary"].ToString());
string BID = (MSQLRD["id"].ToString());
BCIT.TopicSaved1 = TC;
BCIT.CategoriesSaved1 = CT;
BCIT.SummarySaved1 = SM;
BLOGID.Text = BID;
BCIT.TotalBodyStackLayout1.Add("Hello");
}
}
BCITLIST.Add(BCIT);
MSQLRD.Close();
string Query1 = "SELECT * FROM test.blogbodytable where `BlogID` = '" + BLOGID.Text + "' ";
MySqlCommand cmd1 = new MySqlCommand(Query1, conn);
MySqlDataReader MSQLRD1 = cmd1.ExecuteReader();
if (MSQLRD1.HasRows)
{
while (MSQLRD1.Read())
{
string BLOGBODY ;
BLOGBODY = (MSQLRD1["BlogBody"].ToString());
BCIT.TotalBodyStackLayout1.Add(BLOGBODY);
}
}
BCITLIST.Add(BCIT);
conn.Close();
return BCITLIST;
}
from my code the line BCIT.TotalBodyStackLayout1.Add("Hello"); in the first reader does add "hello" to the BCIT.TotalBodyStacklayout1, but the line BCIT.TotalBodyStackLayout1.Add( BLOGBODY); does not work, what am i doing wrong?
Can you be more specific what you mean by 'BCIT.TotalBodyStackLayout1.Add(BLOGBODY);' does not work. Are you getting any exception? or if BLOGBODY coming empty? There are few primitive troubleshooting steps you can perform to nail-down the issue
confirm what BLOGID.Text you are getting from your previous query and corresponding data is available in test.blogbodytable for that id.
if (MSQLRD1.HasRows) is resolving to true
Were you able to get inside while (MSQLRD1.Read())
I have a string array which consists of identifiers. I want to get some values from SQL using these identifiers . Is there a way of adding them with a string value to SqlCommand parameters?
I want to create a query like:
select CaseList from MasterReportData where Id = 1 OR Id = 2 OR Id = 3
This is my C# code:
public static List<string> GetCaseList(string[] masterIdList)
{
try
{
string query = " select CaseList from MasterReportData where #masterId";
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand(query, conn);
cmd.Parameters.AddWithValue("masterId", ***);
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
list.Add(reader[0].ToString());
}
}
conn.Close();
}
catch (Exception e)
{
var err= 0;
}
return list;
}
There are many different ways you can go about doing this but I prefer to create a temp table of possible values. That way you can do something like
select CaseList from MasterReportData where Id IN(select Id from tempTable)
The best approach (with sql optimization) would be:
Create your Type:
CREATE TYPE dbo.IntTTV AS TABLE
( Id int )
Your Ids:
var ids = new List<int>
{
1,
2,
3,
}
Create a schema:
var tableSchema = new List<SqlMetaData>(1)
{
new SqlMetaData("Id", SqlDbType.Int) // I think it's Int
}.ToArray();
Create the table in C#
var table = ids
.Select(i =>
{
var row = new SqlDataRecord(tableSchema);
row.SetInt32(0, i);
return row;
})
.ToList();
Create the SQL Parameter
var parameter = new SqlParameter();
parameter.SqlDbType = SqlDbType.Structured;
parameter.ParameterName = "#Ids";
parameter.Value = table;
parameter.TypeName = "dbo.IntTTV";
var parameters = new SqlParameter[1]
{
parameter
};
Slightly change your query (this is just an example:)
string query = "select mrd.CaseList from MasterReportData mrd"
+ " inner join #ids i on mrd.Id = i.id";
public static List<string> GetCaseList(string[] masterIdList)
{
List<string> list = new List<string>();
try
{
string query = "select CaseList from MasterReportData where ";
using (SqlConnection conn = new SqlConnection(connString))
{
int i = 0;
SqlCommand cmd = new SqlCommand(query, conn);
for(i = 0; i < masterIdList.Length; i++)
{
var parm = "#ID" + i;
cmd.Parameters.Add(new SqlParameter(parm, masterIdList[i]));
query += (i > 0 ? " OR " : "") + " Id = " + parm;
}
cmd.CommandText = query;
//cmd.Parameters.AddWithValue("masterId", ***);
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
list.Add(reader[0].ToString());
}
}
}
}
catch (Exception e)
{
e.ToString();
}
return list;
}
Hello guys I am trying to do some stuff while reading. What I am trying to do is edit row which was just read. But I get error. Maybe u have some suggestions how should I fix it, to make it work without quitting the data reader. P.S: Ignore that, that queries are open for SQL injections .
string select = "Select * FROM ivykiai WHERE `Ivikio diena` MOD Periodiskumas_d = 0 AND `Ivikio diena` > 0 AND `Ivikio diena` < `Dif dien`";
MySqlCommand command = new MySqlCommand(select, cnn);
MySqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
db1 = (now - Convert.ToDateTime(reader["Nuo"])).TotalDays;
MessageBox.Show(db1.ToString());
db1 = db1 - Convert.ToInt32(reader["Ivikio diena"]);
MessageBox.Show(db1.ToString());
b = Convert.ToInt32(db1) / Convert.ToInt32(reader["Periodiskumas_d"]);
MessageBox.Show(b.ToString());
a =+ Convert.ToInt32(reader["Suma"]);
MessageBox.Show(a.ToString());
a = a * b;
MessageBox.Show(a.ToString());
string prideti = "Update Lesos Set Grynieji=Grynieji + '"+ a +"'";
MySqlCommand prideti_cmd = new MySqlCommand(prideti, cnn);
string p = prideti_cmd.ExecuteNonQuery().ToString();
string update = "UPDATE Ivikiai Set `Ivykio diena`+= '" + db1 + "'";
MySqlCommand update_cmd = new MySqlCommand(update, cnn);
string u = update_cmd.ExecuteNonQuery().ToString();
}
reader.Close();
cnn.Close();
You can't execute prideti_cmd and update_cmd using the same connection inside the while (reader.Read()) block and reader is still open, however you can do that outside the while (reader.Read()) block and after closing reader. I would suggest creating the following class
public class MyClass
{
public DateTime Nuo { get; set; }
public int IvikioDiena { get; set; }
public int Periodiskumas_d { get; set; }
public int Suma { get; set; }
}
and change your code as below
string select = "Select * FROM ivykiai WHERE `Ivikio diena` MOD Periodiskumas_d = 0 AND `Ivikio diena` > 0 AND `Ivikio diena` < `Dif dien`";
using (MySqlCommand command = new MySqlCommand(select, cnn))
{
// execute the select query and store the results to list variable
List<MyClass> list = new List<MyClass>();
using (MySqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
MyClass record = new MyClass();
record.Nuo = Convert.ToDateTime(reader["Nuo"]);
record.IvikioDiena = Convert.ToInt32(reader["Ivikio diena"]);
record.Periodiskumas_d = Convert.ToInt32(reader["Periodiskumas_d"]);
record.Suma = Convert.ToInt32(reader["Suma"]);
list.Add(record);
}
}
// enumerate list and execute both the update queries
foreach (var record in list)
{
db1 = (now - record.Nuo).TotalDays;
MessageBox.Show(db1.ToString());
db1 = db1 - record.IvikioDiena;
MessageBox.Show(db1.ToString());
b = Convert.ToInt32(db1) / record.Periodiskumas_d;
MessageBox.Show(b.ToString());
a =+ record.Suma;
MessageBox.Show(a.ToString());
a = a * b;
MessageBox.Show(a.ToString());
string prideti = "Update Lesos Set Grynieji=Grynieji + '"+ a +"'";
MySqlCommand prideti_cmd = new MySqlCommand(prideti, cnn);
string p = prideti_cmd.ExecuteNonQuery().ToString();
string update = "UPDATE Ivikiai Set `Ivykio diena`+= '" + db1 + "'";
MySqlCommand update_cmd = new MySqlCommand(update, cnn);
string u = update_cmd.ExecuteNonQuery().ToString();
}
}
Generally you can ever only have one active command - SQL Server MARS being a little exceptiohn.
So, you can not use a connection WHILE IT HAS AN OPEN READER. Your first need to finish reading, then can update- or use anothe connection, which will get you into transaction isolation troubles.
Try this:
using (MySqlConnection cnn = new MySqlConnection(dbConnectionString))
{
cnn.Open();
MySqlCommand command = new MySqlCommand(select, cnn);
using (MySqlDataReader reader = command.ExecuteReader())
{
db1 = (now - Convert.ToDateTime(reader["Nuo"])).TotalDays;
MessageBox.Show(db1.ToString());
db1 = db1 - Convert.ToInt32(reader["Ivikio diena"]);
MessageBox.Show(db1.ToString());
b = Convert.ToInt32(db1) / Convert.ToInt32(reader["Periodiskumas_d"]);
MessageBox.Show(b.ToString());
a = +Convert.ToInt32(reader["Suma"]);
MessageBox.Show(a.ToString());
a = a * b;
MessageBox.Show(a.ToString());
}
string prideti = "Update Lesos Set Grynieji=Grynieji + '" + a + "'";
MySqlCommand prideti_cmd = new MySqlCommand(prideti, cnn);
string p = prideti_cmd.ExecuteNonQuery().ToString();
string update = "UPDATE Ivikiai Set `Ivykio diena`+= '" + db1 + "'";
MySqlCommand update_cmd = new MySqlCommand(update, cnn);
string u = update_cmd.ExecuteNonQuery().ToString();
}
All of the variables needed for the ExecuteNonQuery() are set when the data is read so you can use them outside the MySqlDataReader.ExecuteReader() function.
I tried below code for cheking SP is alredy exist or not. if not exist i am creating..
But every time it is showing sp is not created.....But my database already have this sp.
Let me know where i am doing mistake.
string checkSP = String.Format(
"IF OBJECT_ID('{0}', 'U') IS NOT NULL SELECT 'true' ELSE SELECT 'false'",
"GP_SOP_AdjustTax");
SqlCommand command = new SqlCommand(checkSP, myConnection);
command.CommandType = CommandType.Text;
if (myConnection == null || myConnection.State == ConnectionState.Closed)
{
try
{
myConnection.Open();
}
catch (Exception a)
{
MessageBox.Show("Error " + a.Message);
}
}
bool Exist = false;
Exist = Convert.ToBoolean(command.ExecuteScalar());
if (Exist == false) //false : SP does not exist
{
// here i am writing code for creating SP
}
Try:
if exists(select * from sys.objects where type = 'p' and name = '<procedure name>' )
Also you can check that with c#:
string connString = "";
string query = "select * from sysobjects where type='P' and name='MyStoredProcedureName'";
bool spExists = false;
using (SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
using (SqlCommand command = new SqlCommand(query, conn))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
spExists = true;
break;
}
}
}
}
For those who use Entity Framework and a DbContext:
create an extension class for DbContext:
internal static class DbContextExtensions
{
public static bool StoredProcedureExists(this DbContext context,
string procedureName)
{
string query = String.Format(
#"select top 1 from sys.procedures " +
"where [type_desc] = '{0}'", procedureName);
return dbContext.Database.SqlQuery<string>(query).Any();
}
}
As robIII remarked, this code should not be published to the outside world as it makes the database vulnerable for hackers (thank you RobIII!). To prevent this use a parameterized statement. The problem with the above mentioned method is described here
The solution is to put procedureName as a parameter in an SQL statement. SQL will check if the string parameter has the desired format, thus inhibiting malicious calls:
public static bool ImprovedExists(this DbContext dbContext, string procedureName)
{
object[] functionParameters = new object[]
{
new SqlParameter(#"procedurename", procedureName),
};
const string query = #"select [name] from sys.procedures where name= #procedurename";
return dbContext.Database.SqlQuery<string>(query, functionParameters).Any();
}
I found this on MSDN
select * from sys.objects where type_desc = 'SQL_STORED_PROCEDURE' AND name = 'Sql_PersonInsert'
Try:
SELECT *
FROM sys.objects
WHERE object_id = OBJECT_ID(N'GP_SOP_AdjustTax') AND type in (N'P', N'PC')
My stab at it:
Reusable extension method
Minimal Sql / Minimal C#
Called from .Net as the OP implicitly requested
Could be faster because of the object_id function
public static bool StoredProcedureExists(this string source)
{
using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
conn.Open();
using (var cmd = new SqlCommand($"select object_id('{source}')", conn))
return !cmd.ExecuteScalar().ToString().IsNullOrWhiteSpace();
}
}
You can check with following tsql query (suitable for SQL Server):
select * from sysobjects where ytype='P' and name='MyStoredProcedureName'
If query returns row then stored procedure named 'MyStoredProcedureName' exists.
And here is how you can use it in code:
//TODO: set connection string
string connString = "";
string query = "select * from sysobjects where ytype='P' and name='MyStoredProcedureName'";
bool spExists = false;
using (SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
using (SqlCommand command = new SqlCommand(query,conn))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
spExists = true;
break;
}
}
}
}
string checkSP = String.Format(
"IF OBJECT_ID('{0}', 'U') IS NOT NULL SELECT 'true' ELSE SELECT 'false'",
"GP_SOP_AdjustTax");
is fine if you change the 'U' to 'P'.
With 'U' you query for user-tables, where 'P' gives you stored-procedures.
private static bool StoredProcedureExists(string sp)
{
var connString = #"<your string here>";
var query = string.Format("SELECT COUNT(0) FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = '{0}'", sp);
using (var conn = new SqlConnection(connString))
{
conn.Open();
using (var cmd = new SqlCommand(query, conn))
{
return Convert.ToInt32(cmd.ExecuteScalar()) > 0;
}
}
}
Handles procedure names with different schemas
Names with and without brackets ([])
Uses parameter to avoid SQL injection
Note: Caller owns SQL Connection
public static class SqlConnectionExtensions
{
public static Task<bool> StoredProcedureExistsAsync(this SqlConnection sqlConnection, string storedProcedureName)
{
string query = "SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(#storedProcedureName) AND type in (N'P', N'PC')";
using (SqlCommand command = new SqlCommand(query, sqlConnection))
{
command.Parameters.AddWithValue("#storedProcedureName", storedProcedureName);
using (SqlDataReader reader = command.ExecuteReader())
{
return reader.ReadAsync();
}
}
}
}
The following works with MySQL, SQL Server, and Oracle I think:
SELECT * FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_TYPE='PROCEDURE'
AND (ROUTINE_SCHEMA='questionnaire' OR ROUTINE_CATALOG = 'questionnaire')
AND SPECIFIC_NAME='create_question';
Usage:
string procedureName = "create_question";
using (DbConnection conn = new SqlConnection("Server=localhost;Database=questionnaire;Trusted_Connection=True;")) // Connection is interchangeable
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = $"SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_TYPE='PROCEDURE' AND (ROUTINE_SCHEMA='{conn.Database}' OR ROUTINE_CATALOG = '{conn.Database}') AND SPECIFIC_NAME='{procedureName}';";
return cmd.ExecuteScalar() != null;
}
}
If you use Microsoft.SqlServer.Management.Smo, try
private static bool CheckIfStoredProcedureExists(Database db, string spName, string schema)
{
db.StoredProcedures.Refresh();
return (db.StoredProcedures[spName, schema] != null);
}
Try this;
if object_id('YourStoredProcedureName') is null
exec ('create procedure dbo.YourSp as select 1')
go
alter procedure dbo.YourStoredProcedure
as