Insert image in Oracle Database using OleDb from a C# application - c#

I want to insert a PNG image into an OracleDatabase using OleDb and a C# application. The table looks like this:
CREATE TABLE Plant
(
Id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY,
Name VARCHAR2(50) NOT NULL,
Image BLOB null,
CONSTRAINT plant_pk PRIMARY KEY (Id)
);
Below is the code:
public static void AddBinaryParameterToCommand(OleDbCommand cmd, string parameterColumn, object parameter)
{
if (cmd != null)
{
if (parameter != null && !parameter.ToString().Equals(""))
{
OleDbParameter blobParameter = new OleDbParameter();
blobParameter.OleDbType = OleDbType.LongVarBinary;
blobParameter.Direction = ParameterDirection.InputOutput;
blobParameter.ParameterName = parameterColumn;
blobParameter.Value = parameter;
cmd.Parameters.Add(blobParameter);
}
else
cmd.Parameters.Add(new OleDbParameter(parameterColumn, DBNull.Value));
}
}
public int InsertPlant(string name, byte[] image)
{
int id = 0;
using (var connection = new OleDbConnection(ConnectionString))
{
var commandGetIdText = #"SELECT MAX(id) FROM PLANT";
connection.Open();
using (var command = new OleDbCommand(commandGetIdText, connection))
{
using (var reader = command.ExecuteReader())
{
reader.Read();
id = int.Parse(reader[0].ToString()) + 1;
}
}
var commandText = string.Format("INSERT INTO PLANT(ID,NAME,IMAGE) VALUES (?, ?, ?)");
using (var command = new OleDbCommand(commandText, connection))
{
Utils.AddParameterToCommand(command, "ID", id);
Utils.AddParameterToCommand(command, "NAME", name);
Utils.AddBinaryParameterToCommand(command, "IMAGE", image);
command.ExecuteNonQuery();
connection.Close();
}
}
return id;
}
private void button_UploadMap_Click(object sender, EventArgs e)
{
var openFileDialog = new OpenFileDialog
{
Multiselect = true
};
var path = string.Empty;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
path = openFileDialog.FileName;
}
else
{
return;
}
byte[] imageArray = File.ReadAllBytes(path);
var palletMapDL = new PalletMapDL("Data Source=192.168.1.21/orcl;Persist Security Info=True; Password=test;User ID=test; Provider=MSDAORA; OLEDB.NET=True; PLSQLRSet=1");
palletMapDL.InsertPlant("Test Plant 01", imageArray);
When execute command.ExecuteNonQuery(); I got this error message:
System.InvalidOperationException: 'Command parameter[2] '' data value
could not be converted for reasons other than sign mismatch or data
overflow.
OleDbException: 'MSDAORA' failed with no error message available,
result code: DB_E_ERRORSOCCURRED(0x80040E21).
Do you know what could be the issue?
Thanks

Related

How to bulk update 1000 records using C#/SQL

I am reading from a table with a million records, I perform some modifications to some columns and I would like to save them back in bulk. I would like to perform a bulk update after every 10000 records.
I'm using .Net Core 3.1
My code :
public void FixText()
{
SqlConnection cnn = new SqlConnection(strConn);
string queryString = "SELECT ClientID, ServerName, Text FROM [dbo].[Client]";
SqlCommand selectCmd = new SqlCommand(queryString, cnn);
cnn.Open();
int j = 0;
SqlDataReader reader = selectCmd.ExecuteReader();
List<Client> clients = new List<Client>();
try
{
while (reader.Read())
{
j++;
ClientID = (int)reader["ClientID"];
ServerName = reader["ServerName"].ToString();
Text = reader["Text"].ToString();
//Modify Text & set ServerName
string Text = UpdateText(Text);
if text.StartWith("doo"){ServerName = "re";}
//perform bulk update
if (j > 10000)
{
Client client = new Client()
{
ClientID = (int)ClientID,
ServerName = ServerName,
Text = Text,
};
clients.Add(client);
//I'm struggling here on what to use to do a bulk update
j = 0;
}
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
reader.Close();
}
cnn.Close();
}
Any Help is appreciated!
You have two options, either use MERGE statement, or UPDATE.
I will do UPDATE option, as it's the easiest one. (This would need FastMember nuget).
private void ExecuteSql(SqlConnection connection , string sql , SqlParameter[] parameters = null)
{
if(connection == null)
{
throw new ArgumentNullException(nameof(connection));
}
if(string.IsNullOrWhiteSpace(sql))
{
throw new ArgumentNullException(nameof(sql));
}
using(var command = new SqlCommand(sql , connection))
{
if(parameters?.Length > 0)
{
command.Parameters.AddRange(parameters);
}
if(connection.State != ConnectionState.Open)
connection.Open();
command.ExecuteNonQuery();
}
}
private void ExecuteBulkCopy<T>(SqlConnection connection , IEnumerable<T> entries , string destinationTableName , string[] columns = null , int batchSize = 1000000)
{
if(connection == null)
{
throw new ArgumentNullException(nameof(connection));
}
if(entries == null)
{
throw new ArgumentNullException(nameof(entries));
}
if(string.IsNullOrWhiteSpace(destinationTableName))
{
throw new ArgumentNullException(nameof(destinationTableName));
}
if(connection.State != ConnectionState.Open)
connection.Open();
using(SqlBulkCopy sbc = new SqlBulkCopy(connection)
{
BulkCopyTimeout = 0 ,
DestinationTableName = destinationTableName ,
BatchSize = batchSize
})
{
using(var reader = ObjectReader.Create(entries , columns))
{
sbc.WriteToServer(reader);
}
}
}
private IEnumerable<Client> GetUpdatedClients(SqlConnection connection)
{
using(var command = new SqlCommand("SELECT ClientID, ServerName, Text FROM [dbo].[Client]", connection))
{
connection.Open();
using(SqlDataReader reader = _connection.ExecuteReader(query , parameters))
{
if(reader.HasRows)
{
while(reader.Read())
{
if(reader.IsDBNull(x)) { continue; }
var clientId = (int)reader["ClientID"];
var serverName = reader["ServerName"]?.ToString();
var text = reader["Text"]?.ToString();
//Modify Text & set ServerName
string textUpdated = UpdateText(text);
if(textUpdated.StartWith("doo"))
{
serverName = "re";
}
var client = new Client()
{
ClientID = clientId,
ServerName = serverName,
Text = textUpdated
};
yield return client;
}
}
}
}
}
private void BulkUpdateClients(SqlConnection connection, IEnumerable<Client> clients)
{
const string dropTempTable = "IF OBJECT_ID('[tempdb].[dbo].[##Client]') IS NOT NULL DROP TABLE [tempdb].[dbo].[##Client];";
// drop temp table if exists
ExecuteSql(connection ,dropTempTable);
// create the temp table
ExecuteSql($"SELECT TOP 1 [ClientID], [ServerName], [Text] INTO [tempdb].[dbo].[##Client] FROM [dbo].[Client];");
// copy rows to the temp table
ExecuteBulkCopy(connection, clients , "[tempdb].[dbo].[##Client]", new[] { "ClientID", "ServerName", "Text" });
// Use UPDATE JOIN
ExecuteSql("UPDATE t1 SET [ServerName] = t2.[ServerName], [Text] = t2.[Text] FROM [dbo].[Client] t1 JOIN [tempdb].[dbo].[##Client] t2 ON t1.[ClientID] = t2.[ClientID];");
// drop temp table
ExecuteSql(connection,dropTempTable);
}
public void BulkUpdateClients()
{
try
{
using(var connection = new SqlConnection(strConn))
{
connection.Open();
var clients = GetUpdatedClients(connection);
// it's important to use the same connection and keep it a live
// otherwise the temp table will be dropped.
BulkUpdate(connection, clients);
}
}
catch(Exception ex)
{
throw ex;
}
}
If you don't need to use temp table, you can change it to a permanent table (just change the temp table name).
To resolve this there are two ways.
You can use User-Defined Types or Sending array of record as JSON datatype through store procedure
UDT
OPENJSON

How to update database records even if the image is not changed

I am using localDB as my database.
I have an employee table, and the employee images are stored in another table
This is my stored procedure for create and update:
IF NOT EXISTS (SELECT *
FROM dbo.Employee
WHERE employee_id=#employee_id)
BEGIN TRY
BEGIN TRAN
INSERT INTO dbo.Employee
(employee_name,
city,
department,
gender
)
OUTPUT inserted.employee_id
INTO #employee_id_PK (employee_id)
VALUES
(#employee_name,
#city,
#department,
#gender
)
SELECT #FK_Employee_Image_To_Employee_Table = employee_id
FROM #employee_id_PK
INSERT INTO dbo.Employee_Image
(user_image,
file_extension,
employee_id
)
VALUES
(#user_image,
#file_extension,
#FK_Employee_Image_To_Employee_Table
)
COMMIT TRAN
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0
ROLLBACK TRAN --RollBack in case of Error
RAISERROR (#ErrorMessage, #ErrorSeverity, #ErrorState);
END CATCH
ELSE
BEGIN TRY
BEGIN TRAN
UPDATE e
SET e.employee_name=#employee_name,
e.city=#city,
e.department=#department,
e.gender=#gender
FROM dbo.Employee e, dbo.Employee_Health_Insurance h
WHERE e.employee_id=#employee_id AND h.employee_id=#employee_id
UPDATE i
SET i.user_image=#user_image,
i.file_extension=#file_extension
FROM dbo.Employee_Image i, dbo.Employee e
WHERE i.employee_id=#employee_id AND e.employee_id=#employee_id
COMMIT TRAN
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0
ROLLBACK TRAN --RollBack in case of Error
RAISERROR (#ErrorMessage, #ErrorSeverity, #ErrorState);
END CATCH
This is how I add my records through C#
using (SqlConnection con = new SqlConnection(connectionStringConfig))
using (SqlCommand sqlCmd = new SqlCommand("spCreateOrUpdateData", con))
{
try
{
con.Open();
sqlCmd.CommandType = CommandType.StoredProcedure;
//Employee Record
sqlCmd.Parameters.Add("#employee_id", SqlDbType.NVarChar).Value = EmployeeId;
sqlCmd.Parameters.Add("#employee_name", SqlDbType.NVarChar, 250).Value = txtEmpName.Text;
sqlCmd.Parameters.Add("#city", SqlDbType.NVarChar, 50).Value = txtEmpCity.Text;
sqlCmd.Parameters.Add("#department", SqlDbType.NVarChar, 50).Value = txtEmpDept.Text;
sqlCmd.Parameters.Add("#gender", SqlDbType.NVarChar, 6).Value = cboEmpGender.Text;
//Employee Image
sqlCmd.Parameters.Add("#user_image", SqlDbType.VarBinary, 8000).Value = ConvertImageToByteArray(pictureBox1.Image); <-----------------error here according to StackTrace
sqlCmd.Parameters.Add("#file_extension", SqlDbType.VarChar, 12).Value = lblFileExtension.Text;
int numRes = sqlCmd.ExecuteNonQuery();
string ActionType = (btnSave.Text == "Save") ? "Saved" : "Updated";
if (numRes > 0)
{
MessageBox.Show($"{ txtEmpName.Text }'s record is { ActionType } successfully !!!");
RefreshData();
}
else
MessageBox.Show($"{txtEmpName.Text} Already Exist !!!");
}
catch (Exception ex)
{
MessageBox.Show($"Cannot INSERT or UPDATE data! \nError: { ex.Message }");
}
This is how I convert my image to byte[] array:
byte[] ConvertImageToByteArray(Image img)
{
//with memory stream:
/*[1]
using (MemoryStream ms = new MemoryStream())
{
img.Save(ms, img.RawFormat);<-----------------error here according to StackTrace
return ms.ToArray();
}*/
/*[2]
using (MemoryStream ms = new MemoryStream())
{
img.Save(ms, img.RawFormat);<-----------------error here according to StackTrace
byte[] arrImage = ms.GetBuffer();
return arrImage;
}*/
// with image converter
/*ImageConverter converter = new ImageConverter();
return (byte[])converter.ConvertTo(img, typeof(byte[]));*/ <-------------error here according to StackTrace
}
I have tried the above code when converting image to byte array, it is successful when I INSERT it to database, but when I UPDATE a record (e.g. changed the "Employee's name") without changing the image it will display an error: "A generic error occurred at GDI+."
EDIT:
Does it have something to do with retreiving the image?
I do not diplay my image binary data on my datagridview but I display/retreive my image like this:
private void dgvEmpDetails_CellClick(object sender, DataGridViewCellEventArgs e)
{
try
{
if (e.RowIndex != -1)
{
DataGridViewRow row = dgvEmpDetails.Rows[e.RowIndex];
EmployeeId = row.Cells[0].Value?.ToString();
txtEmpName.Text = row.Cells[1].Value?.ToString();
txtEmpCity.Text = row.Cells[2].Value?.ToString();
txtEmpDept.Text = row.Cells[3].Value?.ToString();
cboEmpGender.Text = row.Cells[4].Value?.ToString();
//Display user image
using (SqlConnection con = new SqlConnection(connectionStringConfig))
using (SqlCommand sqlCmd = new SqlCommand("SELECT user_image, file_extension FROM dbo.Employee_Image WHERE employee_id=#employee_id", con))
{
con.Open();
sqlCmd.Parameters.Add("#employee_id", SqlDbType.NVarChar).Value = EmployeeId;
using (SqlDataReader reader = sqlCmd.ExecuteReader())
{
if (reader.HasRows)
{
reader.Read();
pictureBox1.Image = ConvertByteArrayToImage((byte[])(reader.GetValue(0))); <------------- displaying the image here
lblFileExtension.Text = reader.GetValue(1).ToString();
}
else
{
pictureBox1.Image = null;
}
}
}
btnSave.Text = "Update";
btnDelete.Enabled = true;
}
}
catch (Exception ex)
{
MessageBox.Show($"Something is wrong with the selected record! \nError: { ex.GetType().FullName }");
}
}
My method in converting byte array to image:
public static Image ConvertByteArrayToImage(byte[] byteArrayIn)
{
using (MemoryStream ms = new MemoryStream(byteArrayIn))
{
Image returnImage = Image.FromStream(ms);
return returnImage;
}
}
I already solved this problem by modifying this approach: https://stackoverflow.com/a/14866755/11565087
This is my code for converting the image from my pictureBox into byte[]:
public static byte[] ImageToBytes(Image userImage)//Get bytes of the image
{
using (MemoryStream ms = new MemoryStream())
using (Bitmap tempImage = new Bitmap(userImage))
{
/*copy the object (userImage) into a new object (tempImage),
then use that object(tempImage) to "Write" */
tempImage.Save(ms, userImage.RawFormat);
return ms.ToArray();
}
}
This is my code for converting my image's binary data from the database and load it to my pictureBox:
public static Image BytesToImage(byte[] buffer) //Get image from database
{
using (MemoryStream ms = new MemoryStream(buffer))
{
return Image.FromStream(ms);
}
}
This is my approach for getting images from database
// This method use to update the form.
private void loadFormWithID(int ID)
{
dbServer conn = new dbServer(sysController.getConn);
DataTable tbl = conn.getQueryList("SELECT * FROM Products WHERE ID = " + ID);
DataRow row = tbl.Rows[0];
// This is how i update the Picture Box
pictureBoxItem.Image = row["Image"] == DBNull.Value ? pictureBoxItem.InitialImage : ImageController.bytesToImage((byte[])row["Image"]);
}
This is my dbserver class which communicates with database.
public class dbServer
{
public string _connectionLink;
public dbServer(string connectionString)
{
_connectionLink = connectionString;
}
public DataTable getQueryList(string sqlQuery)
{
DataTable tbl = new DataTable();
using (SqlConnection conn = new SqlConnection(_connectionLink))
{
using (SqlCommand cmd = new SqlCommand(sqlQuery, conn))
{
conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
tbl.Load(reader);
}
}
return tbl;
}
}
I hope this solves the Issue.

Properly read the column data type in ms access database

How to properly get the Data Type of MS Access table
Below is my code:
var con = $"Provider=Microsoft.Jet.OLEDB.4.0;" +
$"Data Source={database};" +
"Persist Security Info=True;";
using (OleDbConnection myConnection = new OleDbConnection())
{
myConnection.ConnectionString = con;
myConnection.Open();
DataTable dt = myConnection.GetSchema("Tables");
var l = myConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
var isTableExist = false;
foreach (DataRow item in l.Rows)
{
var tbleName = item[2].ToString();
if (tbleName == tableName)
{
isTableExist = true;
break;
}
}
if (isTableExist)
{
string sql = string.Format($"SELECT * FROM {tableName}");
using (OleDbCommand cmd = new OleDbCommand(sql, myConnection))
{
using (OleDbDataReader reader = cmd.ExecuteReader())
{
if (reader != null)
{
for (int i = 0; i < reader.FieldCount; i++)
{
Console.WriteLine(reader.GetName(i));
Console.WriteLine(reader.GetDataTypeName(i));
}
}
}
}
}
}
Here is the structure of the mdb file im reading
And this is what i'm receiving
id
DBTYPE_I4
main_id
DBTYPE_I4
Document_ID
DBTYPE_WVARCHAR
End_page
DBTYPE_WVARCHAR
No_pages
DBTYPE_I4
Why does the AutoNumber datatype show the same as the number data type?
What i'm doing here is merging tables. And i want to skip the insert statement for those data type AutoNumber but i can't make it work because the result is the same with number. Thank you

checking user name or user email already exists

I am working in a simple registration page where the user can't enter the same user name or email, I made a code that prevent the user from entering the username and it worked but when I tried to prevent the user from entring the same username or email it didn't work.
and my question is, "How can I add another condition where the user can't enter email that already exists?"
I tried to do it in this code, but it did't work:
protected void Button_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection( ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString );
SqlCommand cmd1 = new SqlCommand("select 1 from Table where Name =#UserName", con);
SqlCommand cmd2 = new SqlCommand("select 1 from Table where Email=#UserEmail", con);
con.Open();
cmd1.Parameters.AddWithValue("#UserName", Name_id.Text);
cmd2.Parameters.AddWithValue("#UserEmail", Email_id.Text);
using (var dr1 = cmd1.ExecuteReader())
{
if (dr1.HasRows)
{
Label1.Text = "user name already exists";
}
using (var dr2 = cmd2.ExecuteReader())
{
if (dr2.HasRows)
{
Label1.Text = "email already exists";
}
else
{
dr1.Close();
dr2.Close();
//add new users
con.Close();
}
}
}
}
but i get this error:
There is already an open DataReader associated with this Command which must be closed first.
Like I said in my comment your design is bad !
First you should have Data Access Layer. This should be project in big solutions but in your case you can put it like new directory. In this directory you create SqlManager class here is the code:
public class SqlManager
{
public static string ConnectionString
{
get
{
return ConfigurationManager.ConnectionStrings["DevConnString"].ConnectionString;
}
}
public static SqlConnection GetSqlConnection(SqlCommand cmd)
{
if (cmd.Connection == null)
{
SqlConnection conn = new SqlConnection(ConnectionString);
conn.Open();
cmd.Connection = conn;
return conn;
}
return cmd.Connection;
}
public static int ExecuteNonQuery(SqlCommand cmd)
{
SqlConnection conn = GetSqlConnection(cmd);
try
{
return cmd.ExecuteNonQuery();
}
catch
{
throw;
}
finally
{
conn.Close();
}
}
public static object ExecuteScalar(SqlCommand cmd)
{
SqlConnection conn = GetSqlConnection(cmd);
try
{
return cmd.ExecuteScalar();
}
catch
{
throw;
}
finally
{
conn.Close();
}
}
public static DataSet GetDataSet(SqlCommand cmd)
{
return GetDataSet(cmd, "Table");
}
public static DataSet GetDataSet(SqlCommand cmd, string defaultTable)
{
SqlConnection conn = GetSqlConnection(cmd);
try
{
DataSet resultDst = new DataSet();
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
{
adapter.Fill(resultDst, defaultTable);
}
return resultDst;
}
catch
{
throw;
}
finally
{
conn.Close();
}
}
public static DataRow GetDataRow(SqlCommand cmd)
{
return GetDataRow(cmd, "Table");
}
public static DataRow GetDataRow(SqlCommand cmd, string defaultTable)
{
SqlConnection conn = GetSqlConnection(cmd);
try
{
DataSet resultDst = new DataSet();
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
{
adapter.Fill(resultDst, defaultTable);
}
if (resultDst.Tables.Count > 0 && resultDst.Tables[0].Rows.Count > 0)
{
return resultDst.Tables[0].Rows[0];
}
else
{
return null;
}
}
catch
{
throw;
}
finally
{
conn.Close();
}
}
}
After that you should have Business Object Layer. In bigger solution is project in your case directory. If you are in the page TaxesEdit.aspx, you should add Tax.cs class in the BO(business object).
Example of methods for the class, for your first button:
public DataSet GetTaxesByUserName(string userName)
{
SqlCommand cmd = new SqlCommand(#"
select 1 from Table where Name =#UserName");
cmd.Parameters.AddWithValue("#UserName", userName);
return DA.SqlManager.GetDataSet(cmd);
}
You fetch all the needed data in datasets. After that you make checks like taxesDst.Tables[0].Rows.Count > 0 (or == 0)
For Insert you can have method like this:
public virtual void Insert(params object[] colValues)
{
if (colValues == null || colValues.Length % 2 != 0)
throw new ArgumentException("Invalid column values passed in. Expects pairs (ColumnName, ColumnValue).");
SqlCommand cmd = new SqlCommand("INSERT INTO " + TableName + " ( {0} ) VALUES ( {1} )");
string insertCols = string.Empty;
string insertParams = string.Empty;
for (int i = 0; i < colValues.Length; i += 2)
{
string separator = ", ";
if (i == colValues.Length - 2)
separator = "";
string param = "#P" + i;
insertCols += colValues[i] + separator;
insertParams += param + separator;
cmd.Parameters.AddWithValue(param, colValues[i + 1]);
}
cmd.CommandText = string.Format(cmd.CommandText, insertCols, insertParams);
DA.SqlManager.ExecuteNonQuery(cmd);
}
For this you need to have property TableName in the current BO class.
In this case this methods can be used everywhere and you need only one line of code to invoke them and no problems like yours will happen.
You have opened another DataReader inside the First and thats causing the problem. Here I have re-arranged your code a bit
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
SqlCommand cmd1 = new SqlCommand("select 1 from Table where Name =#UserName", con),
cmd2 = new SqlCommand("select 1 from Table where Email=#UserEmail", con);
con.Open();
cmd1.Parameters.AddWithValue("#UserName", Name_id.Text);
cmd2.Parameters.AddWithValue("#UserEmail", Email_id.Text);
bool userExists = false, mailExists = false;
using (var dr1 = cmd1.ExecuteReader())
if (userExists = dr1.HasRows) Label1.Text = "user name already exists";
using (var dr2 = cmd2.ExecuteReader())
if (mailExists = dr2.HasRows) Label1.Text = "email already exists";
if (!(userExists || mailExists)) {
// can add User
}
You need to close one datareader before opening the other one. Although it's not how I'd do it, but you can deal with the runtime error by closing the datareader after each IF:
using (var dr1 = cmd1.ExecuteReader())
{
if (dr1.HasRows)
{
string Text = "user name already exists";
}
dr1.Close();
}
using (var dr2 = cmd2.ExecuteReader())
{
if (dr2.HasRows)
{
string ext = "email already exists";
}
else
{
//add new users
}
dr2.Close();
}
con.Close();
This may work, although there are a few things I would do differently...
protected void Button_Click(object sender, EventArgs e)
{
bool inputIsValid = true;
var con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
var userNameCmd = new SqlCommand("SELECT 1 FROM Table WHERE Name = #UserName", con);
var emailCmd = new SqlCommand("SELECT 1 FROM Table WHERE Email = #UserEmail", con);
con.Open();
userNameCmd.Parameters.AddWithValue("#UserName", Name_id.Text);
emailCmd.Parameters.AddWithValue("#UserEmail", Email_id.Text);
using (var userNameReader = userNameCmd.ExecuteReader())
{
if (userNameReader.HasRows)
{
inputIsValid = false;
Label1.Text = "User name already exists";
}
}
using (var emailReader = emailCmd.ExecuteReader())
{
if (emailReader.HasRows)
{
inputIsValid = false;
Label1.Text = "Email address already exists";
}
}
if (inputIsValid)
{
// Insert code goes here
}
con.Close();
}
Why don't you do something like this:
[Flags]
public enum ValidationStatus
{
Valid = 0 ,
UserNameInUse = 1 ,
EmailInUse = 2 ,
}
public ValidationStatus ValidateUser( string userName , string emailAddr )
{
ValidationStatus status ;
string connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString ;
using ( SqlConnection con = new SqlConnection( connectionString ) )
using ( SqlCommand cmd = con.CreateCommand() )
{
cmd.CommandText + #"
select status = coalesce( ( select 1 from dbo.myTable t where t.UserName = #UserName ) , 0 )
+ coalesce( ( select 2 from dbo.myTable t where t.UserEmail = #UserEmail ) , 0 )
" ;
cmd.Parameters.AddWithValue( "#UserName" , userName ) ;
cmd.Parameters.AddWithValue( "#emailAddr" , emailAddr ) ;
int value = (int) cmd.ExecuteScalar() ;
status = (ValidationStatus) value ;
}
return status ;
}
Aside from anything else, hitting the DB twice for something like this is silly. And this more clearly expresses intent.
Then you can use it in your button click handler, something like this:
protected void Button_Click( object sender , EventArgs e )
{
string userName = Name_id.Text ;
string emailAddr = Email_id.Text ;
ValidationStatus status = ValidateUser( userName , emailAddr ) ;
switch ( status )
{
case ValidationStatus.Valid :
Label1.Text = "" ;
break ;
case ValidationStatus.EmailInUse :
Label1.Text = "Email address in use" ;
break ;
case ValidationStatus.UserNameInUse :
Label1.Text = "User name in use" ;
break ;
case ValidationStatus.EmailInUse|ValidationStatus.UserNameInUse:
Label1.Text = "Both user name and email address in use." ;
break ;
default :
throw new InvalidOperationException() ;
}
if ( status == ValidationStatus.Valid )
{
CreateNewUser() ;
}
}

Conversion failed when converting from a string to a uniqueidentifier

When I run my code on debug I get this error:
Conversion failed when converting from a string to a uniqueidentifier
Here is the code:
public class UserObject
{
private string m_name = string.Empty;
public UserObject(string id)
{
#region Internal Logic
try
{
using (SqlConnection cn = new SqlConnection(SiteConfig.ConnectionString))
{
string sSQL = "SELECT [UserName] FROM [aspnet_users] WHERE [UserID] = #UserID";
using (SqlCommand cm = new SqlCommand(sSQL, cn))
{
cm.Parameters.AddWithValue("#UserID", id);
cn.Open();
using (SqlDataReader rd = cm.ExecuteReader())
{
while (rd.Read())
{
m_name = rd[0].ToString();
}
rd.Close();
}
cn.Close();
}
}
}
catch (Exception ex)
{
}
#endregion Internal logic
}
}
You said in your comment to the question that id does not have a value when being passed into the method. From the database point of view, uniqueidentifiers can be null (DBNull in C#), but to achieve this, you'd have to leave out the parameter or set DBNull.Value explicitly.
In C#, Guid can not be null - so you must either provide Guid.Empty or a string that can be converted to a Guid in the call to AddWithValue.
EDIT
Sample code follows: Please note that given the SQL statement you use, you won't get any results for the Guid.Empty case unless you have a user the ID of which contains only 0s. I suggest, you change the where clause of your SQL statement as follows:
WHERE [UserId] = ISNULL(#UserID, [UserId])
That way, you get all users when you pass null.
public UserObject(string id)
{
try
{
using (SqlConnection cn = new SqlConnection(SiteConfig.ConnectionString))
{
string sSQL = "SELECT [UserName] FROM [aspnet_users] WHERE [UserID] = #UserID";
using (SqlCommand cm = new SqlCommand(sSQL, cn))
{
if (id.Length == 0)
cm.Parameters.AddWithValue("#UserID", Guid.Empty);
else if (id == null)
cm.Parameters.AddWithValue("#UserID", DBNull.Value);
else
cm.Parameters.AddWithValue("#UserID", Guid.Parse(id));
cn.Open();
using (SqlDataReader rd = cm.ExecuteReader())
{
while (rd.Read())
{
m_name = rd[0].ToString();
}
rd.Close();
}
cn.Close();
}
}
}
catch (Exception ex)
{
}

Categories