I have written a function to insert some data into SQL table based on the data received from the client iny my LINQ to SQL class:
//some code
string commString = "INSERT INTO Token (tk_ID, tk_token, tk_date, tk_IP) VALUES (#val1, #val2, #val3, #val4)";
string conString = "placeholder";
token = GenerateToken(clientLoginData);
using (SqlConnection con = new SqlConnection(conString))
{
using (SqlCommand com = new SqlCommand())
{
com.Connection = con;
com.CommandText = commString;
com.Parameters.AddWithValue("#val1", clientLoginData.cl_ID);
com.Parameters.AddWithValue("#val2", token);
com.Parameters.AddWithValue("#val3", clientLoginData.LoginTime);
com.Parameters.AddWithValue("#val4", clientLoginData.cl_IP);
try
{
con.Open();
com.ExecuteNonQuery();
}
catch (SqlException e)
{
}
}
//rest of function
Is this the correct way to do so? I heard you can do it much easier using
SampleDBDataContext dc = new SampleDBDataContext();
and then using this variable dc. I never used it however, is it true? And can someone give me example of inserting one value into the table using this?
your code is a simple c# code to insert value and not Linq2Sql for Linq2Sql you should have
using (YourDbContext dc=new YourDbContext ()){
Token item = new Token();
item.tk_date = clientLoginData.LoginTime;
item.tk_IP = clientLoginData.cl_IP;
item.tk_ID = clientLoginData.cl_ID;
item.tk_token = token;
dc.Tokens.InsertOnSubmit
dc.SubmitChanges();
}
Example 1
Example 2
Do like this:
DataContext dc = new Using(DataContext(Connections.GetDynamicConnectionfromConfig()))
{
Sampleclass obj = new Sampleclass();
//Here assign properties to obj
dc.tableName.InsertOnSubmit(obj);
dc.SubmitChanges();
}
Hope this will help you.
your code should look like this
using (SampleDBDataContext dc = new SampleDBDataContext())
{
Token item = new Token();
item.tk_ID = clientLoginData.cl_ID;
item.tk_token = token;
item.tk_date = clientLoginData.LoginTime;
item.tk_IP = clientLoginData.cl_IP;
dc.Tokens.InsertOnSubmit(item);
dc.SubmitChanges();
}
Related
I'm writing an API controller that inserts and updates records in a table. I'm able to insert new items into the database pretty easily, but I'm having a hard time understanding how to update existing records. My current solution is to query the number of records that have the same UserName and DeviceId as the request. If the count is > 0, then we execute the update query. Else, we execute the insert query. But I'm not sure how to return the count of records from the countQuery. Also, I would rather not use the patch or put methods for this. I want all the logic in the post method. Thanks for your help!
public BaseResponse Post([FromBody]PendingAttachmentRequest pending)
{
var datasource = "";
var appVersion = "";
var sessionId = "";
var updateQuery = "UPDATE PendingAttachments SET PendingCount = #PendingCount,LastUpdated = #LastUpdated,DataSource = #DataSource WHERE DeviceId = #deviceId AND WHERE UserName = #userName";
var countQuery = "SELECT count(*) PendingAttachments WHERE DeviceId = #DeviceId AND WHERE UserName = #UserName";
MobileCompleteServer.Helpers.Connection.GetHeaderInfo(out sessionId, out datasource, out appVersion);
using (var onbaseConnection = MobileCompleteServer.Helpers.Connection.Connect(sessionId, datasource))
{
var connectionString = System.Configuration.ConfigurationManager.AppSettings["ConnectionString"];
try
{
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
sqlConnection.Open();
using (SqlCommand comm = new SqlCommand(countQuery, sqlConnection))
{
if (/*how to check if the result of countQuery is > 0*/)
{
using (SqlCommand sqlComm = new SqlCommand(updateQuery, sqlConnection))
{
sqlComm.CommandType = System.Data.CommandType.Text;
//replace that row with request body
sqlComm.Parameters.Add(new SqlParameter("#DataSource", pending.DataSource));
sqlComm.Parameters.Add(new SqlParameter("#LastUpdated", pending.LastUpdated));
sqlComm.Parameters.Add(new SqlParameter("#PendingCount", pending.PendingCount));
sqlComm.Parameters.Add(new SqlParameter("#DeviceId", pending.DeviceId));
sqlComm.Parameters.Add(new SqlParameter("#UserName", pending.UserName));
}
}
using (SqlCommand sqlCommand = new SqlCommand("sp_InsertPendingAttachments", sqlConnection))
{
sqlCommand.CommandType = System.Data.CommandType.StoredProcedure;
sqlCommand.Parameters.Add(new SqlParameter("#DataSource", pending.DataSource));
sqlCommand.Parameters.Add(new SqlParameter("#UserName", pending.UserName));
sqlCommand.Parameters.Add(new SqlParameter("#DeviceId", pending.DeviceId));
sqlCommand.Parameters.Add(new SqlParameter("#PendingCount", pending.PendingCount));
sqlCommand.Parameters.Add(new SqlParameter("#LastUpdated", pending.LastUpdated));
sqlCommand.ExecuteNonQuery();
}
}
}
return new BaseResponse();
}
catch (Exception e)
{
if (e.Message == Constants.SessionNotFound)
{
return new BaseResponse
{
Exception = Constants.SessionNotFound,
ExceptionStackTrace = e.ToString()
};
}
else
{
return new BaseResponse
{
Exception = Constants.PendingAttachmentError,
ExceptionStackTrace = e.ToString()
};
}
}
}
}
If you don't care about how many records are there and you just want to check whether at least a record exists or not in table, then use "exists". It will definitely improve query performance. So you need to only check for true or false condition: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/exists-transact-sql?view=sql-server-ver15
You also need to use "ExecuteReader" / "ExecuteScalar" method: Check if a record exists in the database
Try to use Repository design pattern which will separate your data access logic and domain logic and it will also help in making your code testable. Also, Your method is doing lots of things at a time so its violating Single responsibility principle.
Do you not already have a method serving a GET endpoint taking deviceId and userName as parameters? If not create it and call that method to check for existence and, depending on the result, you either call an update or insert handler. That way your API will be more RESTful and modular thus less coupled to the business logic and more testable.
The below code throws an error
The UserId, Password or Account is invalid.
on the code line adapter.Fill(ds);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Teradata.Client.Provider;
using System.Data;
using System.Diagnostics;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
TdConnectionStringBuilder connectionStringBuilder = new TdConnectionStringBuilder();
connectionStringBuilder.DataSource = "URL";
connectionStringBuilder.Database = "DB";
connectionStringBuilder.UserId = "USERNAME";
connectionStringBuilder.Password = "PASSWORD";
connectionStringBuilder.AuthenticationMechanism = "LDAP";
TdConnection cn = new TdConnection();
cn.ConnectionString = connectionStringBuilder.ConnectionString;
cn.Open();
TdCommand cmd = new TdCommand("EXEC MACRO", cn);
TdDataReader reader = cmd.ExecuteReader();
TdDataAdapter adapter = new TdDataAdapter(cmd.CommandText, cn.ConnectionString);
DataSet ds = new DataSet();
adapter.Fill(ds);
// myLabel.Text= ds.Tables[0].Rows[0]["event_id"].ToString();
cmd.Dispose();
cn.Close();
}
}
However, the below code works perfectly fine and returns value as expected.
TdConnectionStringBuilder connectionStringBuilder = new TdConnectionStringBuilder();
connectionStringBuilder.DataSource = "URL";
connectionStringBuilder.Database = "DB";
connectionStringBuilder.UserId = "USERNAME";
connectionStringBuilder.Password = "PASSWORD";
connectionStringBuilder.AuthenticationMechanism = "LDAP";
TdConnection cn = new TdConnection();
cn.ConnectionString = connectionStringBuilder.ConnectionString;
cn.Open();
TdCommand cmd = new TdCommand("Show table DB.TABLE1", cn);
String customers = (String)cmd.ExecuteScalar();
MeanTime.Text = customers;
cmd.Dispose();
cn.Close();
The user ID, Password, Datasource etc are all same yet it fails on 1st code but runs properly on 2nd.
When calling procs and macros you can use the TDCommand.ExecuteNonQuery.
UPDATE: Upon further reading here it looks like you can include the CALL when using the Stored Procedure commandtype. The proper Commandtype for a Macro execution is System.Data.CommandType.Text and you probably need the EXEC
For reference, with parameter binding and a procedure, here's a working example below. Some small tweaks would need to be made (as mentioned above) for a macro execution.
//create a new td connection
TdConnection cn = new TdConnection();
//Build the connection string
TdConnectionStringBuilder connectionStringBuilder = new TdConnectionStringBuilder();
connectionStringBuilder.DataSource = "serveraddress";
connectionStringBuilder.Database = "defaultdatabase";
connectionStringBuilder.UserId = "username";
connectionStringBuilder.Password = "password";
connectionStringBuilder.AuthenticationMechanism = "LDAP";
connectionStringBuilder.CommandTimeout = 120;
//Open the connection
cn.ConnectionString = connectionStringBuilder.ConnectionString;
cn.Open();
// Initialize TdCommand from the tdconnection
TdCommand cmd = cn.CreateCommand();
//CommandText is set to Stored Procedure name, in this case,
//.NET Data Provider will generate the CALL statement.
cmd.CommandText = "yourdatabasename.yourprocname";
cmd.CommandType = CommandType.StoredProcedure;
// Create Input Parameter required by this procedure
TdParameter InParm1 = cmd.CreateParameter();
InParm1.Direction = ParameterDirection.Input;
InParm1.DbType = DbType.String;
InParm1.Size = 20;
InParm1.Value = "yourparamvalue";
//and bind it
cmd.Parameters.Add(InParm1);
//------------OPTION 1 CATCHING AN OUTPUT PARAMETER---------------------
//If you are catching an output parameter from a proc then create here:
// Create Output Parameter.
TdParameter OutParm = cmd.CreateParameter();
OutParm.Direction = ParameterDirection.Output;
OutParm.ParameterName = "myOutputParam";
OutParm.DbType = DbType.String;
OutParm.Size = 200;
cmd.Parameters.Add(OutParm);
// Run it up
cmd.ExecuteReader()
//if this is returning a single value you can grab it now:
myOutput = OutParm.Value.ToString();
//------------OPTION 2 CATCHING A RECORDSET-----------------------------
//list based on class set in seperate model
List<myClass> l_myclass = new List<myClass>();
//run it up and catch into a TDDataRead
using (TdDataReader r = cmd.ExecuteReader())
{
if (r.HasRows)
{
//Loop the result set and catch the values in the list
while (r.Read())
{
//"myclass" class defined in a seperate model
//Obviously you could do whatever you want here, but
//creating a list on a class where the column1-column4 is defined makes short work of this.
//Then you can dump the whole l_myclass as json back to the client if you want.
myClass i = new myClass();
i.column1 = (!r.IsDBNull(0)) ? r.GetString(0) : string.Empty;
i.column2 = (!r.IsDBNull(1)) ? r.GetString(1) : string.Empty;
i.column3 = (!r.IsDBNull(2)) ? r.GetString(2) : string.Empty;
i.column4 = (!r.IsDBNull(3)) ? r.GetString(3) : string.Empty;
l_myClass.Add(i);
}
}
}
//Dump the list out as json (for example)
return Json(l_myClass, System.Web.Mvc.JsonRequestBehavior.AllowGet);
I've only, personally, used this on procedures, but the documentation I've read suggests that this is the correct route for macros as well.
I am trying to get a little tool to work, for our little company.
This should fill data from a DataGridView into a SQL Server Standard database.
Reading out the SQL table is working fine, but I can't get the tool to write the values.
I get the error mentioned in the title.
Here the code:
var kdNummer = new SqlParameter("Kundennummer", SqlDbType.Int);
var kdName = new SqlParameter("Kundenname", SqlDbType.VarChar);
var kdMail = new SqlParameter("Kundenmail", SqlDbType.VarChar);
var kdTele = new SqlParameter("Telefon", SqlDbType.VarChar);
string kdquery = "INSERT INTO Kunden VALUES (#Kundennummer, #Kundenname, #Kundenmail, #Telefon)";
using (SqlConnection updatedb = new SqlConnection("Data Source=;Initial Catalog=updatedb;User ID=;Password="))
{
updatedb.Open();
for (int i = 0;i<dataGridView1.Rows.Count;i++)
{
using(SqlCommand NrDaten = new SqlCommand(kdquery, updatedb))
{
kdNummer.Value = dataGridView1.Rows[i].Cells["Kundennummer"].Value;
NrDaten.Parameters.Add(kdNummer);
NrDaten.ExecuteNonQuery();
}
using (SqlCommand NameDaten = new SqlCommand(kdquery, updatedb))
{
kdName.Value = dataGridView1.Rows[i].Cells["Kundenname"].Value;
NameDaten.Parameters.Add(kdName);
NameDaten.ExecuteNonQuery();
}
using (SqlCommand MailDaten = new SqlCommand(kdquery, updatedb))
{
kdMail.Value = dataGridView1.Rows[i].Cells["Kundenmail"].Value;
MailDaten.Parameters.Add(kdMail);
MailDaten.ExecuteNonQuery();
}
using (SqlCommand TeleDaten = new SqlCommand(kdquery, updatedb))
{
kdTele.Value = dataGridView1.Rows[i].Cells["Telefon"].Value;
TeleDaten.Parameters.Add(kdTele);
TeleDaten.ExecuteNonQuery();
}
}
updatedb.Close();
}
Your query requires 4 parameters, but you're always only setting one (also please note that in the SqlParameter you need to have the # sign as well). Thus you get an error about missing parameters. Your code should probably look like this:
var kdNummer = new SqlParameter("#Kundennummer", SqlDbType.Int);
var kdName = new SqlParameter("#Kundenname", SqlDbType.VarChar);
var kdMail = new SqlParameter("#Kundenmail", SqlDbType.VarChar);
var kdTele = new SqlParameter("#Telefon", SqlDbType.VarChar);
string kdquery = "INSERT INTO Kunden VALUES (#Kundennummer, #Kundenname, #Kundenmail, #Telefon)";
using (SqlConnection updatedb = new SqlConnection("..."))
{
updatedb.Open();
using (SqlCommand insert = new SqlCommand(kdquery, updatedb))
{
insert.Parameters.Add(kdName);
insert.Parameters.Add(kdNummer);
insert.Parameters.Add(kdMail);
insert.Parameters.Add(kdTele);
for (int i = 0;i<dataGridView1.Rows.Count;i++)
{
kdName.Value = dataGridView1.Rows[i].Cells["Kundenname"].Value;
kdNummer.Value = dataGridView1.Rows[i].Cells["Kundennummer"].Value;
kdMail.Value = dataGridView1.Rows[i].Cells["Kundenmail"].Value;
kdTele.Value = dataGridView1.Rows[i].Cells["Telefon"].Value;
insert.ExecuteNonQuery();
}
}
}
Or even shorter:
string kdquery = "INSERT INTO Kunden VALUES (#Kundennummer, #Kundenname, #Kundenmail, #Telefon)";
using (SqlConnection updatedb = new SqlConnection("..."))
{
updatedb.Open();
for (int i = 0;i<dataGridView1.Rows.Count;i++)
{
using (SqlCommand insert = new SqlCommand(kdquery, updatedb))
{
insert.Parameters.AddWithValue("#Kundenname", dataGridView1.Rows[i].Cells["Kundenname"].Value);
insert.Parameters.AddWithValue("#Kundennummer", dataGridView1.Rows[i].Cells["Kundennummer"].Value);
insert.Parameters.AddWithValue("#Kundenmail", dataGridView1.Rows[i].Cells["Kundenmail"].Value);
insert.Parameters.AddWithValue("#Telefon", dataGridView1.Rows[i].Cells["Telefon"].Value);
insert.ExecuteNonQuery();
}
}
}
EDIT: I modified the long version of the code for maximum re-use of instances. Otherwise you get the errors mentioned in your comment.
How to loop through a list of objects in order to pass said object to a method inserting rows in SQL db via stored procedure?
With help in this question I got to this point:
namespace NA.Controllers
{
public class NC : ApiController
{
[Route("AddNote")]
[HttpPost]
public HttpResponseMessage PostNote(List<Note> items)
{
//NoteJson deserializednote = JsonConvert.DeserializeObject<NoteJson>(item);
//Note notesdata = new Note(item);
NotesAccept.Models.INoteRepository Repository = new NotesAccept.Models.NoteDataRepository();
foreach (Note item in items)
{
item = Repository.Add(item);
}
var response = Request.CreateResponse<List<Note>>(HttpStatusCode.OK, items);
return response;
}
}
}
but now I'm stuck as item= is now an iteration variable, but I need to pass it to an method:
namespace NA.Models
{
class NoteDataRepository : INoteRepository
{
public void Add(Note item)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
else
{
String strConnString = ConfigurationManager.ConnectionStrings["conString"].ConnectionString;
SqlConnection con = new SqlConnection(strConnString);
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "BL_IntegrationInsertNote";
cmd.Parameters.Add("#Client", SqlDbType.VarChar).Value = item.Client.Trim();
cmd.Parameters.Add("#Case", SqlDbType.VarChar).Value = item.Case;
cmd.Parameters.Add("#Text", SqlDbType.VarChar).Value = item.Text.Trim();
cmd.Parameters.Add("#When", SqlDbType.DateTime).Value = item.Date;
cmd.Parameters.Add("#Ext", SqlDbType.Bit).Value = item.Type;
cmd.Parameters.Add("#return", SqlDbType.Int).Direction = ParameterDirection.Output;
cmd.Connection = con;
try
{
con.Open();
cmd.ExecuteNonQuery();
string id = cmd.Parameters["#return"].Value.ToString();
string lblMessage = null;
lblMessage = "Record inserted successfully. ID = " + id;
}
catch (Exception ex)
{
throw ex;
}
finally
{
con.Close();
con.Dispose();
}
}
//return item;
}
IEnumerable<Note> INoteRepository.GetAll()
{
throw new NotImplementedException("getitems");
}
}
}
I'm still green-as-a-grass-newbie to C# so I've no idea how to accomplish that, especially since whole solution is still "copy&Paste" from all over the web, and whole web curiously concentrates on looping through simple types. How to do that with complex type?
As noted in other question, this is a matter of professional life and death (I'm a db dev, not a VS guru, especially not after two days and two nights).
You are still forgetting to assign that ID from DB to the item.
You also still have
return item;
in a method that does not return anything (public void Add(Note item)).
So just delete that return line.
And replace
item = Repository.Add(item);
with just
Repository.Add(item);
You can pass it as xml and iterate in sql stored procedure and do bulk insert, or you can use table datatype if sql and .net version you are using supports it.
Try this in the foreach loop:
var tempItem = item;
tempItem = Repository.Add(tempItem);
I'm trying to implement a method which will take a given connection string and return an ArrayList containing the contents of a SQL view.
I've verified the validity of the connection string and the view itself. However I don't see what the problem is in the code below. In debug, when it runs the ExecuteReader method and then try to enter the while loop to iterate through the records in the view, it immediately bails because for some reason sqlReader.Read() doesn't.
public ArrayList GetEligibles(string sConnectionString)
{
string sSQLCommand = "SELECT field1, field2 FROM ViewEligible";
ArrayList alEligible = new ArrayList();
using (SqlConnection sConn = new SqlConnection(sConnectionString))
{
// Open connection.
sConn.Open();
// Define the command.
SqlCommand sCmd = new SqlCommand(sSQLCommand, sConn);
// Execute the reader.
SqlDataReader sqlReader = sCmd.ExecuteReader(CommandBehavior.CloseConnection);
// Loop through data reader to add items to the array.
while (sqlReader.Read())
{
EligibleClass Person = new EligibleClass();
Person.field1 = sqlReader["field1"].ToString();
Person.field2 = sqlReader["field2"].ToString();
alEligible.Add(Person);
}
// Call Close when done reading.
sqlReader.Close();
}
return alEligible;
}
Note, EligibleClass is just a class object representing one row of the view's results.
A couple of things I would check:
Is the connection string ok
Does the user in your connection string have access to the database/view
Can you access that database from the pc your at
Does the ViewEligable view exist
Does the view contain a field1 and field2 column.
Here one way you could possibly clean up that code somewhat (assuming you have .net 2.0)
public List<EligibleClass> GetEligibles(string sConnectionString)
{
List<EligibleClass> alEligible = null;
try
{
using (SqlConnection sConn = new SqlConnection(sConnectionString))
{
sConn.Open();
using (SqlCommand sCmd = new SqlCommand())
{
sCmd.Connection = sConn;
sCmd.CommandText = "SELECT field1, field2 FROM ViewEligible";
using (SqlDataReader sqlReader = sCmd.ExecuteReader())
{
while (sqlReader.Read())
{
EligibleClass Person = new EligibleClass();
Person.field1 = sqlReader.GetString(0);
Person.field2 = sqlReader.GetString(1);
if (alEligible == null) alEligible = new List<EligibleClass>();
alEligible.Add(Person);
}
}
}
}
}
catch (Exception ex)
{
// do something.
}
return alEligible;
}