I'm trying to return an object in C#. In JavaScript, I would do this:
function myFunction () {
var myObj = { firstName: "John", lastName: "Smith", age: 20};
return myObj;
}
Everything I'm reading about returning an object within C# is much different than this so it's throwing me for a loop.
What I want to do is run a query to SQL to get some user info and return the users Role, Full Name, Email, etc...
Here is my current C# Code:
public static string getUserRole(string connectionString, string userId)
{
string role;
SqlConnection sqlCon = new SqlConnection(connectionString);
SqlCommand sqlCom = new SqlCommand();
SqlDataReader reader;
sqlCom.CommandText = "SELECT Role FROM myDatabase.Table WHERE Email = '" + userId + "'";
sqlCom.CommandType = CommandType.Text;
sqlCom.Connection = sqlCon;
sqlCon.Open();
reader = sqlCom.ExecuteReader();
if (reader.Read())
{
role = reader.GetString(0);
sqlCon.Close();
return role;
}
else
{
return "An error has occurred";
}
}
I'm assuming I need to do something like the following but it doesn't work:
public static string getUserRole(string connectionString, string userId)
{
string role;
string fullName;
string email;
SqlConnection sqlCon = new SqlConnection(connectionString);
SqlCommand sqlCom = new SqlCommand();
SqlDataReader reader;
sqlCom.CommandText = "SELECT Role FROM myDatabase.Table WHERE Email = '" + userId + "'";
sqlCom.CommandType = CommandType.Text;
sqlCom.Connection = sqlCon;
sqlCon.Open();
reader = sqlCom.ExecuteReader();
if (reader.Read())
{
public class myObject
{
role = reader.GetString(0);
fullName = reader.GetString(1);
email = reader.GetString(2);
}
sqlCon.Close();
return myObject;
}
else
{
return "An error has occurred";
}
}
I'm probably way off but from what I'm reading, object within c# are basically classes. So that makes sense. I need to create a class that defines my properties. Is this correct? I've ready lots of posts and watched some youtube videos but none are 'clicking'
Thanks in advance for any helpful input.
public class UserInfo
{
public string role;
public string fullName;
public string email;
public string ErrorCode;
}
and then change signatures to
public static UserInfo getUserRole(string connectionString, string userId)
and then change
if (reader.Read())
{
public class myObject
{
role = reader.GetString(0);
fullName = reader.GetString(1);
email = reader.GetString(2);
}
sqlCon.Close();
return myObject;
}
else
{
return "An error has occurred";
}
to create an object of UserInfo and return that. Like,
UserInfo info = new UserInfo();
if (reader.Read())
{
info.role = reader.GetString(0);
info.fullName = reader.GetString(1);
info.email = reader.GetString(2);
sqlCon.Close();
}
else
{
info.ErrorCode = "An error has occurred";
}
return info;
Note: Not the best way to do it, but should get you going. Just to give you an idea.
Related
I am making a web service get data from sql server. I need to get many fields from the sql server, but I can only get one field, which is the Currancy Name
namespace WebApplication2
{
public class DataHelper
{
public static string GetCurrency(string currencyCode)
{
string currencyName = "";
SqlConnection con = new SqlConnection(#"Data Source=WEB3\SHAREPOINT;Initial Catalog=WSS_Search_WEB3;Integrated Security=True");
SqlCommand cmd = new SqlCommand("select PO_NUMBER,PO_STATUS from View_1 where PO_HEADER_ID ='" + currencyCode.ToUpper() + "'", con);
con.Open();
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
currencyName = dr["PO_NUMBER"].ToString();
}
dr.Close();
con.Close();
return currencyName;
}
}
}
I need to get the PO_Number & PO Status from the Query
As I understand you need to return not only PO_NUMBER, but also PO_STATUS, and as I understand you want to return both values.
I suggest you make model that represent what you want to return.
So for that we make a model class call it for instance POModel:
public class POModel
{
public string currencyName { get; set; } // PO_Number
public string statusName { get; set; } // PO_Status
}
Than fetch the values from SQL as you did and return object in stead of string.
Here would you final code looks like, of course naming and all the stuff you can change the way if fits best:
public class DataHelper
{
public static POModel GetCurrency(string currencyCode)
{
//string currencyName = "";
var poModel = new POModel();
SqlConnection con = new SqlConnection(#"Data Source=WEB3\SHAREPOINT;Initial Catalog=WSS_Search_WEB3;Integrated Security=True");
SqlCommand cmd = new SqlCommand("select PO_NUMBER,PO_STATUS from View_1 where PO_HEADER_ID ='" + currencyCode.ToUpper() + "'", con);
con.Open();
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
poModel.currencyName = dr["PO_NUMBER"].ToString();
poModel.statusName = dr["PO_STATUS"].ToString();
}
dr.Close();
con.Close();
//return currencyName;
return poModel;
}
}
public class POModel
{
public string currencyName { get; set; }
public string statusName { get; set; }
}
One option is to return an array that contains the two values. Notice string[]:
public static string[] GetCurrency(string currencyCode)
Similar to how you declared string currencyName = "";, instead make an array variable:
string[] poData = new string[2];
Since this looks like it should return a single row, I would not loop. Just do a Read():
dr.Read();
poData[0] = dr["PO_NUMBER"].ToString(); //poData[] will have to be declared in your method
poData[1] = dr["PO_STATUS"].ToString();
....
return poData;
Is there a way i can reuse this codes in executing SQL transaction, i want to make it a method so i can put parameters to execute other stored procedures,
can you guys help me to design a good coding structure?
try {
using (SqlConnection con = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand("InsertUser2Sp", con) {
CommandType = CommandType.StoredProcedure
}) {
cmd.Parameters.AddWithValue("#UserID", useridStr);
cmd.Parameters.AddWithValue("#Firstname", firstnStr);
cmd.Parameters.AddWithValue("#Middlename", middleNstr);
cmd.Parameters.AddWithValue("#Lastname", lastnStr);
cmd.Parameters.AddWithValue("#UserAge", ageInt);
cmd.Parameters.AddWithValue("#HomeAddress", homeaddStr);
con.Open();
cmd.ExecuteNonQuery();
}
}
} catch (Exception ex) {
MessageBox.Show("Could not connect to database. Check settings. " + ex.Message, "Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
MessageBox.Show(ex.Message);
}
}
I will share a generic method here . All you need to do is to build an object with the same property names (including cases) same with the parameters in your SP.
protected internal string GetSingleValue_String(String spname, Object entity)
{
Object res = new Object();
String conString = String.Empty;
using (SqlConnection con = new SqlConnection(ConnectionString))
{
con.Open();
SqlCommand cmd = new SqlCommand(spname, con);
cmd.CommandType = CommandType.StoredProcedure;
if (entity != null)
{
SqlCommandBuilder.DeriveParameters(cmd);
PropertyInfo entitymember = default(PropertyInfo);
foreach (SqlParameter _param in cmd.Parameters)
{
if (_param.Direction == ParameterDirection.Input)
{
entitymember = entity.GetType().GetProperty(_param.ParameterName.Replace("#", ""));
var entityValue = entitymember.GetValue(entity, null);
String _paramvalue = entityValue != null ? entityValue.ToString() : null;
_param.Value = (string.IsNullOrEmpty(_paramvalue) || _paramvalue == string.Empty ? null : _paramvalue);
}
}
}
res = cmd.ExecuteScalar();
cmd.Connection.Close();
entity = null;
cmd = null;
if(res==null)
res = "";
else if (String.IsNullOrEmpty(res.ToString()))
res = "";
return res.ToString();
}
}
So in your example, create a new class that have the same definition as your SP parameters.
class NewClass()
{
public string UserID { get; set; }
public string Firstname { get; set; }
public string Middlename { get; set; }
public string Lastname { get; set; }
public string UserAge { get; set; }
public string HomeAddress { get; set; }
}
And will call the method like this.
var newClass = new NewClass
{
UserID = "UserId",
Firstname = "Firstname",
Middlename = "Middlename",
Lastname = "Lastname",
UserAge = "UserAge",
HomeAddress = "HomeAddress"
}
var res = GetSingleValue_String("InsertUser2Sp", newClass);
Don'd mind the return type.
This is probably my first C# program, so i kindly ask for you patience.
Im trying to create an app that adds/deletes/updates student data from a local MS Sql database by following an online tutorial.
Database- local windows authentication called with table Registration:
primary key- UserId int
UserName varchar (100)
Password varchar (20)
Country varchar (100)
email varchar (20)
The program uses a WCF service and it starts correctly, however i keep getting the error when i try to invoke the InsertUserDetails().
Error text:
The parameterized query '(#UserID int,#UserName nvarchar(4000),#Password nvarchar(4000),#' expects the parameter '#UserName', which was not supplied.
C# code for Service1.cs:
public class Service1 : IService1
{
public DataSet SelectUserDetails()
{
SqlConnection con = new SqlConnection(#"Server=Robert;Database=Trying;Trusted_Connection=True;");
con.Open();
SqlCommand cmd = new SqlCommand("Select * from Registration", con);
SqlDataAdapter sda = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
sda.Fill(ds);
cmd.ExecuteNonQuery();
con.Close();
return ds;
}
public void UpdateRegistrationTable(UserDetails userInfo)
{
SqlConnection con = new SqlConnection(#"Server=Robert;Database=Trying;Trusted_Connection=True;");
con.Open();
SqlCommand cmd = new SqlCommand("update Registration set UserName=#UserName,Password=#Password,Country=#Country, Email=#Email where UserID=#UserID", con);
cmd.Parameters.AddWithValue("#UserName", userInfo.UserName);
cmd.Parameters.AddWithValue("#Password", userInfo.Password);
cmd.Parameters.AddWithValue("#Country", userInfo.Country);
cmd.Parameters.AddWithValue("#Email", userInfo.Email);
cmd.ExecuteNonQuery();
con.Close();
}
public bool DeleteUserDetails(UserDetails userInfo)
{
SqlConnection con = new SqlConnection(#"Server=Robert;Database=Trying;Trusted_Connection=True;");
con.Open();
SqlCommand cmd = new SqlCommand("delete from Registration where UserID=#UserID", con);
cmd.Parameters.AddWithValue("#UserID", userInfo.UserID);
cmd.ExecuteNonQuery();
con.Close();
return true;
}
public string InsertUserDetails(UserDetails userInfo)
{
string Message;
SqlConnection con = new SqlConnection(#"Server=Robert;Database=Trying;Trusted_Connection=True;");
con.Open();
SqlCommand cmd = new SqlCommand("insert into Registration(UserID,UserName,Password,Country,Email) values(#UserID,#UserName,#Password,#Country,#Email)", con);
cmd.Parameters.AddWithValue("#UserID", userInfo.UserID);
cmd.Parameters.AddWithValue("#UserName", userInfo.UserName);
cmd.Parameters.AddWithValue("#Password", userInfo.Password);
cmd.Parameters.AddWithValue("#Country", userInfo.Country);
cmd.Parameters.AddWithValue("#Email", userInfo.Email);
int result = cmd.ExecuteNonQuery();
if (result == 1)
{
Message = userInfo.UserName + " Details inserted successfully";
}
else
{
Message = userInfo.UserName + " Details not inserted successfully";
}
con.Close();
return Message;
}
}
}
C# code for IService1.cs
[ServiceContract]
public interface IService1
{
[OperationContract]
string InsertUserDetails(UserDetails userInfo);
[OperationContract]
DataSet SelectUserDetails();
[OperationContract]
bool DeleteUserDetails(UserDetails userInfo);
[OperationContract]
void UpdateRegistrationTable(UserDetails userInfo);
}
// Use a data contract as illustrated in the sample below to add composite types to service operations.
[DataContract]
public class UserDetails
{
int userid;
string username;
string password;
string country;
string email;
[DataMember]
public int UserID
{
get { return userid; }
set { userid = value; }
}
[DataMember]
public string UserName
{
get { return username; }
set { username = value; }
}
[DataMember]
public string Password
{
get { return password; }
set { password = value; }
}
[DataMember]
public string Country
{
get { return country; }
set { country = value; }
}
[DataMember]
public string Email
{
get { return email; }
set { email = value; }
}
}
}
That means that the UserName Property of your UserDetails class seems to be null. Check if it has a value.
One way to mitigate such errors is to check the validity of the UserDetails instance in advance by specifiying the contract of your insert method.
public string InsertUserDetails(UserDetails userInfo)
{
if(null==userInfo)
throw new Exception("userInfo is null");
if(String.IsNullOrEmpty(userInfo.UserName))
throw new Exception("UserName is null or empty");
// and only after this check succeeds do the insert
}
If you want to allow null values you would have to translate the .NET NULL to the ado.NET DBNull.Value.
cmd.Parameters.AddWithValue("#UserName", userInfo.UserName ?? DBNull.Value);
Another possible solution would be to wrap your SQL in procedures and make the parameter nullable by providing a default parameter.
create procedure usp_InserProc #UserName varchar(32) = NULL
begin
... sql code
end
There is a private "Employee" class object that mirrors the public struct "empStruct". I need to read in the rows values from the query using SQLReader to populate the struct and then set the object equal to the struct values. I think there is a simpler way but I am very new to this.
public struct empStruct
{
public int eid;
public string lastname;
public string firstname;
public DateTime birthdate;
public DateTime hiredate;
public bool ishourly;
public decimal payrate;
}
public static bool SelectEmployee(int eid)
{
empStruct SelectRecord = new empStruct();
Employee newEmp = new Employee();
string sqlText;
sqlText = "SELECT EID,EID, LastName, FirstName, BirthDate, HireDate, IsHourly, PayRate ";
sqlText += "FROM Employee ";
sqlText += "WHERE EID = #EID ";
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(sqlText, connection);
command.CommandType = CommandType.Text;
command.Parameters.AddWithValue("#EID", eid);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
//Call Read before accessing data.
while (reader.Read())
{
???
}
newEmp = SelectRecord;
}
I understand that everything after "//Call Read..." is incomplete, I can't figure out exactly how this reader thing works.
while (reader.Read())
{
newEmp.eid = (int)reader("EID");
newEmp.firstname = (string)reader("FirstName");
....
}
load up the struct like this perhaps
while (reader.Read()) {
newEmp.lastname = reader.GetString(1);
newEmp.firstname = reader.GetString(2);
}
Hi I have got two methods are returning two different return type of values like int and string and I am executing query inside the method with passing different variables like the below
METHOD 1
private string SelectTransactionHistory(int transactionId, ContextObject contextObject)
{
SqlConnection con;
SqlCommand cmd;
con = new SqlConnection(contextObject.ConnectionString);
con.Open();
string returnvalue = string.Empty;
string selecteQuery = "SELECT Comments
From dbo.TransactionHistory
WHERE TransactionID = '" + transactionId + "'";
cmd = new SqlCommand(selecteQuery, con);
returnvalue = (string)cmd.ExecuteScalar();
con.Close();
return returnvalue;
}
METHOD 2
private int SelectTransactionHistoryID(string comment, ContextObject contextObject)
{
SqlConnection con;
SqlCommand cmd;
con = new SqlConnection(contextObject.ConnectionString);
con.Open();
string query = "SELECT TransactionID
From dbo.TransactionHistory
WHERE Comments = '" + comment + "'";
cmd = new SqlCommand(query, con);
int returnvalue = (int)cmd.ExecuteScalar();
con.Close();
return returnvalue;
}
I am calling these methods in another method like this
int transactionId = SelectTransactionHistoryID(comment, GetContext());
string commentsreturnValue = SelectTransactionHistory(transactionId, GetContext());
how can i combine these two methods to make more generic type..
Would any one have any suggestions on how to do this..
Many Thanks.....
You could create a method to execute any query using ado.net, for sample:
private static T ExecuteQuery<T>(ContextObject contextObject, string query)
{
T result;
using (SqlConnection con = con = new SqlConnection(contextObject.ConnectionString))
{
try
{
con.Open();
using (SqlCommand cmd = cmd = new SqlCommand(query, con))
{
result = (T)cmd.ExecuteScalar();
}
}
catch
{
result = null;
}
finally
{
con.Close();
}
}
returnr result;
}
And pass a query that return a single value (in sql we use TOP 1), something like this:
var resultComment = ExecuteQuery<string>("SELECT TOP 1 Comments From dbo.TransactionHistory WHERE TransactionID = '" + transactionId + "'");
var resultTransactionId = ExecuteQuery<int>("SELECT TOP 1 TransactionID From dbo.TransactionHistory WHERE Comments = '" + comment + "'")
I have all of my infrastructure classes setup to utilize Dapper. However you can replace the dapper extension method with a regular method.
Base Service:
public interface IService
{
T Execute<T>(Func<IDbConnection, T> query);
void Execute(Action<IDbConnection> query);
}
public sealed class Service : IService
{
private readonly string _connectionString;
public Service(string connectionString)
{
_connectionString = connectionString;
}
private IDbConnection CreateConnection()
{
var connection = new SqlConnection(_connectionString);
connection.Open();
return connection;
}
public T Execute<T>(Func<IDbConnection, T> query)
{
using (var connection = CreateConnection())
{
return query(connection);
}
}
public void Execute(Action<IDbConnection> query)
{
using (var connection = CreateConnection())
{
query(connection);
}
}
}
DTO:
public class TransactionHistory
{
public int TransactionID { get; set; }
public string Comments { get; set; }
}
Service:
public interface ITransactionHistoryService
{
IEnumerable<TransactionHistory> GetByTransactionId(int transactionId);
IEnumerable<TransactionHistory> GetByComment(string comment);
}
public sealed class TransactionHistoryService : ITransactionHistoryService
{
// Note SELECT * is frowned upon. Replace with actual column names.
private const string GetByTransactionIdQuery =
"SELECT * FROM dbo.TransactionHistory WHERE TransactionID = #TransactionId";
private const string GetByCommentQuery =
"SELECT * FROM dbo.TransactionHistory WHERE Comments = #Comment";
private readonly IService _service;
public TransactionHistoryService(IService service)
{
_service = service;
}
public IEnumerable<TransactionHistory> GetByTransactionId(int transactionId)
{
var result = _service.Execute(c =>
c.Query<TransactionHistory>(GetByTransactionIdQuery,
new { TransactionId = transactionId }));
return result;
}
public IEnumerable<TransactionHistory> GetByComment(string comment)
{
var result = _service.Execute(c =>
c.Query<TransactionHistory>(GetByCommentQuery,
new { Comment = comment }));
return result;
}
}
You can create a single function as follows- (Not tested)
private string[] SelectTransactionHistory(int transactionId, ContextObject contextObject)
{
string[] returnValues;
SqlConnection con;
SqlCommand cmd;
SqlDataReader reader;
con = new SqlConnection(contextObject.ConnectionString);
con.Open();
string returnvalue = string.Empty;
string selecteQuery = "SELECT TransactionID, Comments From dbo.TransactionHistory WHERE TransactionID = '" + transactionId + "'";
cmd = new SqlCommand(selecteQuery, con);
reader = cmd.ExecuteReader();
while(reader.Read())
{
returnValues[0] = reader["TransactionID"].ToString();
returnValues[1] = reader["Comments"].ToString();
}
con.Close();
return returnValues;
}
And then call it as follows-
string[] TransactionHistory = SelectTransactionHistory(transactionId, GetContext());
int transactionId = Convert.ToInt32(TransactionHistory[0]);
string commentsreturnValue = TransactionHistory[1];
The above code is not tested. But you can get an idea.