I have a table with an identity column.
Using Massive with code like this
var table = new Categories();
var newID = table.Insert(new {CategoryName = "Buck Fify Stuff", Description = "Things I like"});
then
table.Scalar("select scope_identity()");
returns DBNull :(
What do I need to do different to get the actual inserted identity value
The MSDN documentation states that SCOPE_IDENTITY:
"retrieves the last identity values that are generated in any table in the current session"
Looking at the Massive source code, it appears that every call to Scalar() opens a new connection:
/// <summary>
/// Returns a single result
/// </summary>
public virtual object Scalar(string sql, params object[] args) {
object result = null;
using (var conn = OpenConnection()) { // <-- see this ...
result = CreateCommand(sql, conn, args).ExecuteScalar();
}
return result;
}
...
/// <summary>
/// Returns and OpenConnection
/// </summary>
public virtual DbConnection OpenConnection() {
var result = _factory.CreateConnection();
result.ConnectionString = ConnectionString;
result.Open(); // <-- ...and this
return result;
}
Therefore, every time you are doing table.Scalar("select scope_identity()"); you are actually doing this in a new connection (which means a different session/scope).
This explains the DBNull result.
But since you are already doing:
var newID = table.Insert(...)
you might want to inspect the value of newID after the insert happens; I hope you'll find something nice in there.
At least, that's what the code for Insert() leads me to believe:
public virtual dynamic Insert(object o) {
var ex = o.ToExpando();
if (!IsValid(ex)) {
throw new InvalidOperationException("Can't insert: " + String.Join("; ", Errors.ToArray()));
}
if (BeforeSave(ex)) {
using (dynamic conn = OpenConnection()) {
var cmd = CreateInsertCommand(ex);
cmd.Connection = conn;
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT ##IDENTITY as newID";
ex.ID = cmd.ExecuteScalar();
Inserted(ex);
}
return ex;
} else {
return null;
}
}
Related
I am making an API using ASP.netCore to fetch data from teradata. I have 2 store procedure on Teradata DB one for encryption one for description. What I want to achieve is when user call the get method to fetch data, my Store procedure should run first and then it should return all table to user(changed as SP).
I have tried a lot but didn't manage to find any way to call store procedure and Select * table together. If I run the only store procedure OR call only select * table it work. I want to call both (SP and select*) so first SP should run and change the data then return the changed data table.
My codes are following.
Codes for GetDataTable
public IEnumerable<myTable> GetData(IConfiguration _configuration)
{
try
{
myTable TableReturn = new myTable();
List<myTable> dataReturn = new List<myTable>();
var connectionString = _configuration.GetConnectionString("TeradataConnectionString");
using (var connection = new TdConnection(connectionString))
{
'Date_Of_Birth', ENCRYPTEDSTRING);";
TdCommand cmd = new TdCommand("SELECT * FROM Project.myTable;", connection) ;
TdCommand Db = (TdCommand)cmd;
Db.Connection = connection;
connection.Open();
TdDataReader reader = Db.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
var newTable = new myTable();
newTable.Employee_Id = (string)reader.GetString(0);
newTable.First_name = (string)reader.GetString(1);
newTable.Last_Name = (string)reader.GetString(2);
newTable.Date_Of_Birth = (string)reader.GetString(3);
newTable.Phone = (string)reader.GetString(4);
newTable.Em_Position = (string)reader.GetString(5);
dataReturn.Add(newTable);
}
}
else
{
Console.WriteLine("no rows found");
}
}
return dataReturn;
}
catch (Exception e)
{
throw new Exception();
}
}
My codes for store procedure are following
public IEnumerable<DecryptedData> DecryptedData(IConfiguration _configuration)
{
// DecryptedData DecryptedReturn = new DecryptedData();
List<DecryptedData> dataReturn = new List<DecryptedData>();
var connectionString = _configuration.GetConnectionString("TeradataConnectionString");
using (var connection = new TdConnection(connectionString))
{
string command = "CALL Project.Decryption(STATUS,'Project' ,'myTable', 'Date_Of_Birth', ENCRYPTEDSTRING);";
TdCommand cmd = new TdCommand(command, connection);
TdCommand Db = (TdCommand)cmd;
Db.Connection = connection;
connection.Open();
TdDataReader reader = Db.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
var DecryptedData = new DecryptedData();
DecryptedData.Date_Of_Birth = reader.GetString(1);
dataReturn.Add(DecryptedData);
Console.WriteLine(dataReturn);
}
}
else
{
Console.WriteLine("no rows found");
}
}
return dataReturn;
}
conn.Open();
string query = "INSERT INTO Film (Film, Jaartal, Cijfer) VALUES ('" + filmnaam + "','" + jaartal + "','" + cijfer + "')";
string LastID = "SELECT TOP 1 Id FROM Film ORDER BY Id DESC";
SqlCommand cmd = new SqlCommand(query, conn);
SqlCommand cmd2 = new SqlCommand(LastID, conn);
cmd.ExecuteNonQuery();
using (SqlDataReader dr = cmd2.ExecuteReader())
{
while (dr.Read())
{
string ID = dr["Id"].ToString();
string add= "INSERT INTO GenreFilm (FilmId) VALUES ('" + ID + "')";
SqlCommand cmd3 = new SqlCommand(add, conn);
cmd3.ExecuteNonQuery();
}
}
I am trying to add the value (ID) of my (LastID) query to my database table. But i cant seem to do it right. Above is my existing code. Any help/tips will be greatly appreciated!
this does not directly provide a solution but a flow to follow keeping in mind what #ADyson indicated about parameter (SQL-Injection) and what #Dimitry indicated about allowing the database to get the value for you. Hopefully this will assist.
The code has comments sprinkled within. The first class, DemoForOperations is showing how to call the method in the second class Operations. Of course you can call the insert method in operations from wherever you want.
using System;
using System.Data.SqlClient;
namespace StackOverFlowSample
{
public class DemoForOperations
{
public void TheDemo()
{
var ops = new Operations();
var firstName = "Karen";
var lastName = "Payne";
var returningNewId = 0;
if (ops.SampleInsert(firstName,lastName,ref returningNewId))
{
// success, returningNewId has the new key value which can be
// used for whatever you want e.g. as a value for another query.
}
else
{
// failed, you can use the following the
// figure out the issue
var exceptionMessage = ops.Exception.Message;
}
}
}
public class Operations
{
private Exception exception;
public Exception Exception { get { return exception; } }
/// <summary>
/// Insert a record
/// </summary>
/// <param name="FirstName"></param>
/// <param name="LastName"></param>
/// <param name="NewIdentifier">
/// pass in a valid int by ref
/// </param>
/// <returns>
/// true if successful, false otherwise and will set the property
/// Exception so that the caller can see what went wrong
/// </returns>
public bool SampleInsert(string FirstName, string LastName, ref int NewIdentifier)
{
// here we create the connection new but of course a connection can be created
// outside of the method that is in-scope of this method
using (SqlConnection cn = new SqlConnection() { ConnectionString = "TODO" })
{
// setup for insert using parameters
// along with a secondary query to return the new primary key value
var statement = "INSERT INTO Contacts (FirstName,LastName) " +
"VALUES (#FirstName,#LastName); " +
"SELECT CAST(scope_identity() AS int);";
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = cn;
cmd.CommandText = statement;
try
{
// setup our parameters
cmd.Parameters.AddWithValue("#FirstName", FirstName);
cmd.Parameters.AddWithValue("#LastName", LastName);
cn.Open();
// get new primary key
NewIdentifier = Convert.ToInt32(cmd.ExecuteScalar());
return true;
}
catch (Exception ex)
{
exception = ex;
return false;
}
}
}
}
}
}
i have a little problem in my code, i tried to match my textbox value to database, bu i get an error message ...
here is my codes:
my main code;
protected void btnAddNewTopic_Click(object sender, EventArgs e)
{
if (txtbAddNewTopic.Text == "")
{
MessageBox.Show("Please write topic!");
}
else if (goodob.Businness_Layer.AddNewTopic.NewTopicCheckSystem(txtbAddNewTopic.Text) == null)
{
MessageBox.Show("Your added topic is already in site!");
}
else
{
goodob.Businness_Layer.CreateNewTopic.crnewtopic(txtbAddNewTopic.Text);
MessageBox.Show("Your topic has successfully created!");
}
}
and my check code ;
public static goodob.Businness_Layer.AddNewTopic NewTopicCheckSystem(string topic)
{
goodob.Businness_Layer.AddNewTopic xyz = null;
string query = #"SELECT [topic_name]
FROM topic
WHERE topic_name = #topic";
goodob.Class1 connection1 = new goodob.Class1();
connection1.sqlcommand.CommandText = query;
SqlParameter topicparam = new SqlParameter("#topic_name", SqlDbType.VarChar);
topicparam.Value = topic;
connection1.sqlcommand.Parameters.Add(topic);
System.Data.SqlClient.SqlDataReader reader = connection1.sqlcommand.ExecuteReader();
if (!reader.HasRows)
{
connection1.close_connection();
return null;
}
return xyz;
}
i get an error in connection1.sqlcommand.CommandText = query; please help me!
You have done too much confusion in adding parameters,you should add your sqlparameter object i.e.topicparam insted of topic.
use #topic varibale on both places.
or alternativly you can try this short hand
cmd.Parameters.AddWithValue(" #topic",topic);
insted of
SqlParameter topicparam = new SqlParameter("#topic_name", SqlDbType.VarChar);
topicparam.Value = topic;
connection1.sqlcommand.Parameters.Add(topic);
I use this pgm to get value from a column in xmlstring format named partinfo.which is one of the columns in table test.the partinfo column can be treated as another table containing many columns.and i want to read data from one of this column which is installed date in this case.but while executing i am getting a
sql exception: Cannot find either column "partinfo" or the user-defined
function or aggregate "partinfo.query", or the name is ambiguous.how
can i solve this.
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
try {
SqlConnection con = new
SqlConnection("Data Source=NIP007\\SQLEXPRESS;
Initial Catalog=test;User ID=sa;Password=nest123#!");
con.Open();
string query = "SELECT [partinfo].query('.//InstalledDate').value('.','VARCHAR(MAX)')FROM [test]";
SqlCommand cmd = new SqlCommand(query, con);
// StringBuilder builder=new StringBuilder();
// string PartInfo=string.Empty;
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
string str5 =dr.ToString();
if (!string.IsNullOrEmpty(str5))
{
textBox1.Text=str5;
}
}
}
catch(Exception ex)
{
}
}
}
}
It is not clear what exactly where your error lies because, your SQL should work ok (Demo Here) and not return an error, although I am not sure the output is what you would want as it just concatenates all the installed dates in the XML as one long string:
As said in my previous answer if you have multiple Installed Dates per row, you will want to use CROSS APPLY TO get the installed dates as separate rows.
Demo SQL using CROSS APPLY
If you really want the dates concatenated to one string then I'd suggest using a string builder to do this:
try
{
string query = #"SELECT InstalledDate = x.value('InstalledDate[1]', 'DATETIME')
FROM dbo.Test
CROSS APPLY PartInfo.nodes('/DocumentElement/PartInfo') p (x);";
using (var con = new SqlConnection("Data Source=NIP007\\SQLEXPRESS;Initial Catalog=test;User ID=sa;Password=nest123#!"))
using (var cmd = new SqlCommand(query, con))
{
con.Open();
using (var dr = cmd.ExecuteReader())
{
var builder = new StringBuilder();
while (dr.Read())
{
string str5 = dr.GetString(0);
if (!string.IsNullOrEmpty(str5))
{
builder.Append(str5 + ",");
}
}
textBox1.Text = builder.ToString();
}
}
}
catch (Exception ex)
{
}
If this doesn't help can you post the DDL of your table Test and some sample data.
Thanks
This is an interesting problem, and I will do my best to explain. If you have any questions, please ask.
I have written a WCF service that is suppose to communicate with a JAVA client. This service was created via contract first from a WSDL. Now, according to the WCF test client everything works, even testing on a PHP client works as well. But when it comes to the Java client, the request messages and subsequent response messages fail to return: I get a null object SOAP fault. Here is were I think the problem lies:
According to the XSD and WSDL, I have a DateTime value that I am suppose to take in. This dateTime value from the client is of form: 2012-01-01T12:00:00.00Z. Unfortunately, this input is not valid with the built in .NET datetime. So, to get around this, I changed my code to take in a string datatype, convert that string to a Datetime to send it to the database, get a response from the database in that dateTime and convert it back to a string for the response to return a value that is like the one that was inputted.
I built a logger to check to see if the messages were being sent to and from my wcf service. From that, I have identified that messages from the client were not being received. My only guess is that it is because of the datetime issue.
Is there a way to take in a dateTime datatype in the format: 2012-01-01T12:00:00.000Z? If i can, then that will mean that the request will match my datatype and maybe it will work.
Here is some code:
public partial class findSeatsRequest
{
[MessageBodyMemberAttribute(Namespace="http://soa.cs.uwf.edu/airlineData", Order=0, Name="departAirport")]
public string DepartAirport;
[MessageBodyMemberAttribute(Namespace="http://soa.cs.uwf.edu/airlineData", Order=1, Name="arriveAirport")]
public string ArriveAirport;
[MessageBodyMemberAttribute(Namespace="http://soa.cs.uwf.edu/airlineMessage", Order=2, Name="earliestDepartTime")]
public string EarliestDepartTime;
[MessageBodyMemberAttribute(Namespace="http://soa.cs.uwf.edu/airlineMessage", Order=3, Name="latestDepartTime")]
public string LatestDepartTime;
[MessageBodyMemberAttribute(Namespace="http://soa.cs.uwf.edu/airlineMessage", Order=4, Name="minimumSeatsAvailable")]
public int MinimumSeatsAvailable;
[MessageBodyMemberAttribute(Namespace="http://soa.cs.uwf.edu/airlineMessage", Order=5, Name="maximumFlightsToReturn")]
public int MaximumFlightsToReturn;
public findSeatsRequest()
{
}
public findSeatsRequest(string departAirport, string arriveAirport, string earliestDepartTime, string latestDepartTime, int minimumSeatsAvailable, int maximumFlightsToReturn)
{
this.DepartAirport = departAirport;
this.ArriveAirport = arriveAirport;
this.EarliestDepartTime = earliestDepartTime;
this.LatestDepartTime = latestDepartTime;
this.MinimumSeatsAvailable = minimumSeatsAvailable;
this.MaximumFlightsToReturn = maximumFlightsToReturn;
}
}
public partial class findSeatsResponse
{
[MessageBodyMemberAttribute(Namespace="http://soa.cs.uwf.edu/airlineData", Order=0, Name="flight")]
[XmlElementAttribute("flight")]
public System.Collections.Generic.List<flightType> Flight;
public findSeatsResponse()
{
}
public findSeatsResponse(System.Collections.Generic.List<flightType> flight)
{
this.Flight = flight;
}
}
public virtual findSeatsResponse findSeats(findSeatsRequest request)
{
string departAirport = request.DepartAirport;
string arriveAirport = request.ArriveAirport;
string earliestDepartTime = request.EarliestDepartTime;
string latestDepartTime = request.LatestDepartTime;
int minimumSeatsAvailable = request.MinimumSeatsAvailable;
int maximumFlightsToReturn = request.MaximumFlightsToReturn;
SqlCommand cmd = null;
DataSet ds = new DataSet();
List<flightType> flight = new List<flightType>();
EventLogger log = new EventLogger();
findSeatsRequest inValue = new findSeatsRequest();
inValue.DepartAirport = departAirport;
inValue.ArriveAirport = arriveAirport;
inValue.EarliestDepartTime = earliestDepartTime;
inValue.LatestDepartTime = latestDepartTime;
inValue.MinimumSeatsAvailable = minimumSeatsAvailable;
inValue.MaximumFlightsToReturn = maximumFlightsToReturn;
string latestT = inValue.LatestDepartTime.Replace("T", " ");
string latestZ = latestT.Replace("Z", "");
DateTime _latestDepartTime = DateTime.ParseExact(latestZ, "yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture);
string earliestT = inValue.EarliestDepartTime.Replace("T", " ");
string earliestZ = earliestT.Replace("Z", "");
DateTime _earliestDepartTime = DateTime.ParseExact(earliestZ, "yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture);
log.WriteToDataBase(DateTime.Now, "FindSeats", 1, "This is the request: " + inValue);
//Check Maximum Flights
if (inValue.MaximumFlightsToReturn > 100 | inValue.MaximumFlightsToReturn < 0)
{
throw new FaultException(
"You cannot select more than 100 flights to return, or the maximum flights to return is negative.",
new FaultCode("OutOfRange"));
}
// Check Minimum Seats Available.
if (inValue.MinimumSeatsAvailable < 0)
{
throw new FaultException(
"You minimum seats available cannot be negative.",
new FaultCode("OutOfRange"));
}
// Check for valid Departure Airport
if (departAirport != null && departAirport != "ANY")
{
try
{
string strConn = ConfigurationManager.ConnectionStrings["ConnectionString"].ToString();
SqlConnection conn = new SqlConnection(strConn);
conn.Open();
string check = "SELECT DepartAirport FROM Flight WHERE DepartAirport='" + departAirport + "'";
cmd = new SqlCommand(check, conn);
cmd.CommandText = check;
SqlDataReader depAirport;
depAirport = cmd.ExecuteReader();
if (depAirport.HasRows == false)
{
throw new FaultException(
"Invalid Airport code used.",
new FaultCode("Invalid Text Entry"));
}
}
finally
{
if (cmd != null)
cmd.Dispose();
}
}
// Check for valid Arrival Airport
if (arriveAirport != null && arriveAirport != "ANY")
{
try
{
string strConn = ConfigurationManager.ConnectionStrings["ConnectionString"].ToString();
SqlConnection conn = new SqlConnection(strConn);
conn.Open();
string check = "SELECT ArriveAirport FROM Flight WHERE ArriveAirport='" + arriveAirport + "'";
cmd = new SqlCommand(check, conn);
cmd.CommandText = check;
SqlDataReader arrAirport;
arrAirport = cmd.ExecuteReader();
if (arrAirport.HasRows == false)
{
throw new FaultException(
"Invalid Airport code used.",
new FaultCode("Invalid Text Entry"));
}
}
finally
{
if (cmd != null)
cmd.Dispose();
}
}
try
{
string strConn = ConfigurationManager.ConnectionStrings["ConnectionString"].ToString();
SqlConnection conn = new SqlConnection(strConn);
conn.Open();
cmd = new SqlCommand("usp_NewFindSeats", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#DepartureAirport", inValue.DepartAirport));
cmd.Parameters.Add(new SqlParameter("#ArrivalAirport", inValue.ArriveAirport));
cmd.Parameters.Add(new SqlParameter("#EarliestDepTime", _earliestDepartTime));
cmd.Parameters.Add(new SqlParameter("#LatestDepTime", _latestDepartTime));
cmd.Parameters.Add(new SqlParameter("#minSeatsAvailable", inValue.MinimumSeatsAvailable));
cmd.Parameters.Add(new SqlParameter("#maxFlightsRequested", inValue.MaximumFlightsToReturn));
using (SqlDataReader sqlReader = cmd.ExecuteReader())
{
while (sqlReader.Read())
{
flightType Flight = new flightType();
Flight.FlightId = sqlReader.GetString(0);
Flight.DepartAirport = sqlReader.GetString(1);
Flight.ArriveAirport = sqlReader.GetString(2);
Flight.DepartTime = sqlReader.GetDateTime(3).ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
Flight.ArriveTime = sqlReader.GetDateTime(4).ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
Flight.FlightSeatsAvailable = sqlReader.GetInt32(5);
Flight.FlightSeatPriceUSD = sqlReader.GetDouble(6);
flight.Add(Flight);
}
}
For this particular problem, the issue wasn't anything I thought it was in the beginning. Firstly, had to use WrapperNames in my C# code's request operations and the names I used were incorrect.
Secondly, I needed to specify SOAP Body encoding which I had to do within my Interface layer.
[XmlSerializerFormatAttribute(SupportFaults=true, Style=OperationFormatStyle.Document ,Use=OperationFormatUse.Literal)]