Return nested complex types from WCF WebGet - wcf

I've created a wcf data service to return a List of complex type patient. I used the model browser to create a complex type for "Patient" and a complex type for "Contact". I'd like to add a "Contacts" property to "Patient", which would be a List.
How do I add a nested complex type list as a property and return it?
[WebGet]
public List<Patient> GetPatientByID(int tolid)
{
List<Patient> list = new List<Patient>();
// create pds user session record
SqlConnection conn = new SqlConnection("Data Source=server;Initial Catalog=db;User ID=<ID>;Password=<pwd>");
SqlCommand cmd = new SqlCommand();
try
{
// open the connection
conn.Open();
// configure the command
cmd.Connection = conn;
cmd.CommandText = "sp_tol_patient_select";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("tolid", tolid));
// execute the command and convert the decimal value
// returned by ExecuteScalar to an int to get new identity value
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
Patient itm = new Patient();
itm.MRN = reader["UNITNUMBER"].ToString();
itm.AccountNum = reader["ACCTNUM"].ToString();
itm.FullName = reader["PATNAME"].ToString();
itm.BirthDate = reader["BIRTHDATE"].ToString();
itm.Gender = reader["SEX"].ToString();
list.Add(itm);
}
return list;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
finally
{
cmd.Dispose();
conn.Close();
}
}

Related

Can't use retrieved data from one query into another one?

I need to use a variable (edifcodigo) which assigned value is retrieved from one query to insert it in a table by using other query but there is a error that says this variable is not available in actual context. I'm kind of new in aspnet, could anybody know how to figure this out?
This is the code I have:
//Connect to db
string connetionString = #"myconexionstring";
string sql = "SELECT TOP 1 id_proyecto AS codigo FROM DNN_SCO_PROY_CO_PROYECTO_TBL WHERE nombre_proyecto= '"+ uedif +"'";
//find building code by querying the database
try
{
using (SqlConnection conexion = new SqlConnection(connetionString))
{
conexion.Open();
using (SqlCommand query = new SqlCommand(sql, conexion))
{
SqlDataReader result = query.ExecuteReader();
while (result.Read())
{
string edifcodigo = result["codigo"].ToString();
}
}
}
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
//Save referer friend
try
{
using (SqlConnection conn = new SqlConnection(connetionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("DNN_SVI_SCO_DATOS_RECOMIENDA_AMIGO_SP", conn))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add("#DRA_PROYECTO_CLIENTE", System.Data.SqlDbType.VarChar).Value = edifcodigo; ;
}
}
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
That's because you declared the variable inside a different code block. Every time you open a curly bracket, you open a new code block. Every time you close the curly bracket, you close the current code block. Each code block have it's own scope - it can access variables declared in the surrounding code block, but not variables declared in "sibling" code blocks.
Also, please read about parameterized queries and how they protect you from SQL injection, and change your queries accordingly.
Also, you don't need to close the connection between the two commands, and you can reuse a single command instance in this case. Here is an improved version of your code:
//Connect to db
var connetionString = #"myconexionstring";
var sql = "SELECT TOP 1 id_proyecto AS codigo FROM DNN_SCO_PROY_CO_PROYECTO_TBL WHERE nombre_proyecto = #nombre_proyecto";
//find building code by querying the database
try
{
using (var conexion = new SqlConnection(connetionString))
{
conexion.Open();
using (var cmd = new SqlCommand(sql, conexion))
{
cmd.Parameters.Add("#nombre_proyecto", SqlDbType.NVarChar).Value = uedif;
var edifcodigo = cmd.ExecuteScalar();
//Save referer friend
cmd.Parameters.Clear();
cmd.CommandText = "DNN_SVI_SCO_DATOS_RECOMIENDA_AMIGO_SP";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add("#DRA_PROYECTO_CLIENTE", System.Data.SqlDbType.VarChar).Value = edifcodigo; ;
}
}
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
You are declaring the string variable inside your while loop, it loses scope once you exit the while loop, move it's declaration above with:
string connetionString = #"myconexionstring";
string sql = "SELECT TOP 1 id_proyecto AS codigo FROM DNN_SCO_PROY_CO_PROYECTO_TBL WHERE nombre_proyecto= '"+ uedif +"'";
string edifcodigo = "";
You are trying to use a variable that declared in another scope. edifcodigo should be declared in the parent scope of both try blocks.
//Connect to db
string connetionString = #"myconexionstring";
string sql = "SELECT TOP 1 id_proyecto AS codigo FROM DNN_SCO_PROY_CO_PROYECTO_TBL WHERE nombre_proyecto= '"+ uedif +"'";
string edifcodigo=""; // YOU SHOULD DECLARE edifcodigo HERE
and than rest of code will come
//find building code by querying the database
try
{
using (SqlConnection conexion = new SqlConnection(connetionString))
{
conexion.Open();
using (SqlCommand query = new SqlCommand(sql, conexion))
{
SqlDataReader result = query.ExecuteReader();
while (result.Read())
{
edifcodigo = result["codigo"].ToString();
}
}
}
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
//Save referrer friend
try
{
using (SqlConnection conn = new SqlConnection(connetionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("DNN_SVI_SCO_DATOS_RECOMIENDA_AMIGO_SP", conn))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add("#DRA_PROYECTO_CLIENTE", System.Data.SqlDbType.VarChar).Value = edifcodigo; ;
}
}
}
catch (Exception ex)
{
Response.Write(ex.Message);
}

Entity Framework database first does not catches sql Raiserror at the end of a stored procedure

I've been googling around and I have found similar questions but not exactly this case.
I have a sql server 2005 stored procedure which raises an error at the end, after any data processing call.
Create Procedure webzTest(
#nClaPais Int
)
As
Begin
Select * From zPais Where ClaPais = #nClaPais
Raiserror('TEST ERROR!!!', 16, -1)
End
On the client side Entity Framework (Visual Studio 2012) tries to catch the exception, but it ignores it.
public static void webzTestTransaction()
{
using (var ctx = new MyWebEntities())
{
using (var trx = MyTransactionScope.newTransactionScope())
{
var connection = ((IObjectContextAdapter)ctx).ObjectContext.Connection;
connection.Open(); // Open connection explicitly to avoid EF closing and reopening which invokes DTC
try
{
ctx.webzTest(1).ToList();
ctx.webzTest(2).ToList();
trx.Complete();
}
catch (Exception ex)
{
logger.Error(ex);
throw ex;
}
finally
{
connection.Close();
}
}
}
}
The raised error is ignored.
If I put the Raiserror() statement BEFORE the Select then the exception is catched by EF code, but I expect the same behaviour in the above code.
Let me add a similar example using ADO.NET. In ths case, the exception is catched as expected:
SqlConnection conn = new SqlConnection(connectionString);
conn.Open();
SqlTransaction trx = null;
try
{
trx = conn.BeginTransaction(IsolationLevel.ReadUncommitted);
SqlCommand cmd = new SqlCommand();
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Connection = conn;
cmd.CommandText = "webzTest";
cmd.Transaction = trx;
var parClaPais = new SqlParameter("#nClaPais", SqlDbType.Int);
cmd.Parameters.Add(parClaPais);
parClaPais.Value = 1;
SqlDataReader result1 = cmd.ExecuteReader();
parClaPais.Value = 2;
SqlDataReader result2 = cmd.ExecuteReader();
trx.Commit();
trx = null;
}
catch (Exception ex)
{
if (trx != null)
trx.Rollback();
throw ex;
}
finally
{
conn.Close();
}
Then: What is wrong with EF? or Which is the rule to follow in this case?
Thanks in advance

how to insert row in SQL database in ADO.Net Connection oriented mode

I have a database in which a table has name Registration which is used to register the user.
It has only two column one is Username and one is password.
A page named Register.aspx is used for registering the member which have two textbox one is for taking Username(textbox1) and one is for taking password(textbox2) and one button for insert these value in database.
The Main problem is that we cannot write statement like this :
Insert into Registration (Username, password)
values ('TextBox1.text','TextBox2.text')
I am using ADO.net Connection oriented mode, I googled but I didn't find any way to insert row in SQL database in connected mode. Please provide me a idea for inserting this row?
ADO.NET has DataReader which supports Connected mode. All else are disconnected.
DataReader is connected architecture since it keeps conneection open untill all records are fetched
If you want to insert in ADO.NET then you should perform the following steps:
private void btnadd_Click(object sender, EventArgs e)
{
try
{
//create object of Connection Class..................
SqlConnection con = new SqlConnection();
// Set Connection String property of Connection object..................
con.ConnectionString = "Data Source=KUSH-PC;Initial Catalog=test;Integrated Security=True";
// Open Connection..................
con.Open();
//Create object of Command Class................
SqlCommand cmd = new SqlCommand();
//set Connection Property of Command object.............
cmd.Connection = con;
//Set Command type of command object
//1.StoredProcedure
//2.TableDirect
//3.Text (By Default)
cmd.CommandType = CommandType.Text;
//Set Command text Property of command object.........
cmd.CommandText = "Insert into Registration (Username, password) values ('#user','#pass')";
//Assign values as `parameter`. It avoids `SQL Injection`
cmd.Parameters.AddWithValue("user", TextBox1.text);
cmd.Parameters.AddWithValue("pass", TextBox2.text);
Execute command by calling following method................
1.ExecuteNonQuery()
This is used for insert,delete,update command...........
2.ExecuteScalar()
This returns a single value .........(used only for select command)
3.ExecuteReader()
Return one or more than one record.
cmd.ExecuteNonQuery();
con.Close();
MessageBox.Show("Data Saved");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
con.Close();
}
}
try
{
using (var connection = new SqlConnection(yourConnectionString))
{
string queryString = "Select id, name, age from Table where name = #name";
using (var command = new SqlCommand(queryString, Connection))
{
command.Parameters.AddWithValue("#name", name);
Connection.Open();
SqlDataReader dataReader = command.ExecuteReader();
while (dataReader.Read())
{
item = new Item(long.Parse(dataReader[0].ToString()),
dataReader[1].ToString(),
int.Parse(dataReader[2].ToString()));
}
dataReader.Close();
}
}
}
catch (Exception ex)
{
// if exception will happen in constructor of SqlConnection or Command, the // resource can leak but Dispose method will never be called, couse the object was not created yet.
// Trace and handle here
throw;
}
finally
{
}
But ADO.net is useless for enterprice development. You have to have and abstraction from Data Acess Layer and go to entities, not table records
Use the ORM, Luke!
using System.Data.SqlClient;
string cnstr = "server=.;database=dbname;user=username;password=password;";
SqlConnection con = new SqlConnection(cnstr);
SqlCommand cmd = new SqlCommand { Connection = con };
cmd.CommandText = "Insert into Registration (Username, password) values ('#user','#pass')";
cmd.Parameters.AddWithValue("user", TextBox1.text);
cmd.Parameters.AddWithValue("pass", TextBox2.text);
try
{
con.Open();
cmd.ExecuteNonQuery();
}
catch (Exception)
{
//something;
}
finally
{
if (con != null)
con.Close();
}

silverlight C# code

This is coded in Service.svc.cs file
[OperationContract]
public List<Branch> GetAllBranch()
{
List<Branch> Br = new List<Branch>();
using (SqlConnection con = new SqlConnection(myConnectionString))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = "GetBranch";
cmd.Connection = con;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
con.Open();
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
Branch BrName = new Branch();
BrName.Name = Convert.ToString(dr["BranchName"]);
Br.Add(BrName);
}
dr.Close();
}
}
return Br;
}
public class Branch
{
public string Name { get; set; }
}
End of Service file Code----
This is coded in the Form
ServiceClient client= new ServiceClient();
test.GetAllBranchCompleted += (s, ea) =>
{
cboBranch.ItemsSource = ea.Result;
};
client.GetAllBranchAsync();
My requirement is I want to populate all the Names of the Branches that are present in my database.With this code the combobox for BranchName is getting populated but not with the Database records but something like this CRUD.ServiceReference1.ServiceBranch.
CRUD is my solution Name.
Please correct me with this..
Thanks
To get just the name to appear in your ComboBox you need to result a List<string>. Here you are returning a List<Branch>.
So you either need to rework your service code or just extract a list of strings from your ea.Result.
cboBranch.ItemsSource = ea.Result.Select(b => b.Name).ToList();
(from memory)

How to call a CLR Stored Procedure from codebehind of an aspx page?

How to call a CLR Stored Procedure from codebehind of an aspx page?
I am using SqlCommand with commandtext as CLR Stored Procedure name and SqlHelper.ExecuteDataSet() as below.
string connectionString = ConfigurationManager.AppSettings["ConnectDB"];
SqlConnection sn = new SqlConnection(connectionString);
SqlParameter[] sqlParameters = new SqlParameter[1];
sqlParameters[0] = new SqlParameter("#query", SqlDbType.Int);
sqlParameters[0].Value = "SELECT * FROM Inventory";
DataSet ds=new DataSet();
try
{
ds = SqlHelper.ExecuteDataset(sn, "[dbo].[prc_clr]", sqlParameters);
}
catch (Exception ex)
{
throw;
}
But I am getting exception "The stored procedure '[dbo].[prc_clr]' doesn't exist.".
Please help.
It looks like you are trying to mix command text and stored procedure. I don't believe the query can be placed into a parameter and used in that way, so try out either of the two ways below:
string connectionString = ConfigurationManager.AppSettings["ConnectDB"];
SqlConnection sn = new SqlConnection(connectionString);
DataSet ds=new DataSet();
try
{
ds = SqlHelper.ExecuteDataset(sn, CommandType.StoredProcedure, "[dbo].[prc_clr]");
}
catch (Exception ex)
{
throw;
}
or
string connectionString = ConfigurationManager.AppSettings["ConnectDB"];
SqlConnection sn = new SqlConnection(connectionString);
string strsql = "SELECT * FROM Inventory";
DataSet ds=new DataSet();
try
{
ds = SqlHelper.ExecuteDataset(sn, CommandType.Text, strSql);
}
catch (Exception ex)
{
throw;
}
And when you have a parameter(s) do something like:
ds = SqlHelper.ExecuteDataset(sn, CommandType.StoredProcedure, "[dbo].[prc_clr]", new SqlParameter("#CategoryID", 1));