I am recieving the following error message whenever I click the submit button on my form:
Error: System.ArgumentNullException: Value cannot be null. Parameter name: connectionString at
Microsoft.ApplicationBlocks.Data.SqlHelper.ExecuteDataset(String
connectionString, CommandType commandType, String commandText,
SqlParameter[] commandParameters) at
ClassesnWorkshops._Default.GetHousesBySearchCriteria() . . .
I am a beginner with c# and visual studio.
Can anyone tell me why my connection string might be null?
Any ideas how I might resolve this error?
I used the Settings button of the project Properties to create a ConnectionString called connectionString connecting to my Classes database. but this may have been unnecessary, as it did not change the Error.
//Code for my submit button click event:
protected void cmdSearch_Click(object sender, EventArgs e)
{
DataTable objDT = null;
try
{
//Query the database for houses
objDT = GetHousesBySearchCriteria();
//Any houses found?
if (objDT.Rows.Count == 0)
{
//None found - hide repeater, show message
rptHouses.Visible = false;
lblMessage.Text = "No results found";
}
else
{
//Houses found - show repeater, hide message
rptHouses.DataSource = objDT;
rptHouses.DataBind();
rptHouses.Visible = true;
lblMessage.Text = "";
}
}
catch (Exception ex)
{
//Add your own error handling here
lblMessage.Text = "Error: " + ex.ToString();
}
finally
{
//Release memory
objDT = null;
}
}
#endregion
#region GetHousesBySearchCriteria
public DataTable GetHousesBySearchCriteria()
{
//Use the Microsoft Data Application Blocks to query database
DataSet objDS = new DataSet();
SqlParameter[] arParms = new SqlParameter[2];
arParms[0] = new SqlParameter("#Zipcode", SqlDbType.Char);
arParms[0].Value = txtZipCode.Text;
arParms[1] = new SqlParameter("#Miles", SqlDbType.Decimal);
arParms[1].Value = Int16.Parse(cboWithin.SelectedItem.Value);
lblTestParms0.Text = txtZipCode.Text;
lblTestParms1.Text = cboWithin.SelectedValue.ToString();
//Return a DataTable
return SqlHelper.ExecuteDataset(ConfigurationManager.AppSettings["ConnectionString"],
CommandType.StoredProcedure, "spHouses_GetNearZipcode", arParms).Tables[0];
}
#endregion
stored procedure code:
CREATE PROCEDURE [dbo].[spHouses_GetNearZipcode]
#Zipcode char(5),
#Miles decimal(11,6)
AS
--Load close zipcodes into temp table
SELECT ZIP.ZipCode, ZIP.City,
dbo.DistanceFunc(ZIP.Latitude, ZIP.Longitude, RAD.Latitude, RAD.Longitude) As Distance
INTO #TempZips
FROM ZipCodes ZIP, RadiusFunc(#ZipCode, #Miles) RAD
WHERE (ZIP.Latitude BETWEEN RAD.MinLatitude AND RAD.MaxLatitude) AND
(ZIP.Longitude BETWEEN RAD.MinLongitude AND RAD.MaxLongitude) AND
(dbo.DistanceFunc(ZIP.Latitude,ZIP.Longitude,RAD.Latitude,RAD.Longitude) <= #Miles)
--Search Houses table and JOIN to temp zipcodes table
SELECT H.*, Zips.Distance AS Miles
FROM Schools H INNER JOIN
#TempZips Zips ON Zips.ZipCode = H.zip
ORDER BY Zips.Distance
RETURN
I think the ConfigurationManager argument in your ExecuteDataset should look like this:
return SqlHelper.ExecuteDataset(ConfigurationManager.AppSettings["ConnectionString"].ConnectionString, CommandType.StoredProcedure, "spHouses_GetNearZipcode", arParms).Tables[0];
Add ".ConnectionString" after your AppSettings key
When using ConfigurationManager.AppSettings the key values are case sensitive. Is your connection string named
connectionString or ConnectionString
^ ^
Related
I use OleDbDataAdapter and OleDbCommandBuilder to fill DataSet object with database contents, and then update database according to a changes that I made in the DataSet. The problem is that I get the exception: "Concurrency violation: the UpdateCommand affected 0 of the expected 1 records". I've found an explanation of this error:
Because a record could have been modified after it was returned from
the SELECT statement, but before the UPDATE or DELETE statement is
issued, the automatically generated UPDATE or DELETE statement
contains a WHERE clause, specifying that a row is only updated if it
contains all original values and has not been deleted from the data
source. Where an automatically generated update attempts to update a
row that has been deleted or that does not contain the original values
found in the DataSet, the command does not affect any records, and a
DBConcurrencyException is thrown.
That means that auto generated UPDATE command affected 0 rows in the database. I work with paradox(db-file) database and no one changes it except for me. I guess that my program changes the same row two times somewhere. I wanted to debug my program by executing all generated queries manually and finding which one doesn't affect any row(because actually I'm pretty sure that all changes are made only once and the bug is somewhere else))). Is it possible to run auto generated commands manually?
My code is too big and complicated to post it here but generally it works like this(I made a working project and took it from there)
using System;
using System.Data;
using System.Windows.Forms;
using System.Data.OleDb;
namespace OleDBCommandBuilder
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string cs = #"Provider=Microsoft.Jet.OLEDB.4.0;";
cs += #"Data Source=C:\FOLDER\1\SPR_KMZ\;";
cs += #"Extended Properties=Paradox 5.x;";
OleDbConnection Connection = new OleDbConnection();
Connection.ConnectionString = cs;
try
{ Connection.Open(); }
catch (Exception ex)
{ MessageBox.Show("Error openning database! " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Environment.Exit(0); }
string SQLQuery = "SELECT * FROM SPR_KMZ WHERE REZ<>0";
DataSet SPR_KMZ = new DataSet();
OleDbDataAdapter DataAdapter = new OleDbDataAdapter();
DataAdapter.SelectCommand = new OleDbCommand(SQLQuery, Connection);
OleDbCommandBuilder builder = new OleDbCommandBuilder(DataAdapter);
try
{
DataAdapter.Fill(SPR_KMZ);
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(String.Format("Error \n{0}\n{1}", ex.Message, SQLQuery));
Environment.Exit(0);
}
DataRow[] SPR_KMZ_rows = SPR_KMZ.Tables[0].Select("Fkmz=10000912 AND REZ=1");
foreach (DataRow SPR_KMZ_row in SPR_KMZ_rows)
{
SPR_KMZ_row["DN"] = Convert.ToDateTime("30.12.1899");//26.12.2008
SPR_KMZ_row["Price"] = Convert.ToDouble(0);//168,92
}
DataAdapter.Update(SPR_KMZ);
System.Windows.Forms.MessageBox.Show("Success!");
Environment.Exit(0);
}
}
}
P.S. Previously it updated the database without concurrency exception, but after a lot of changes(I commented out the line "DataAdapter.Update(SPR_KMZ);" for a long time for debugging reason, so I don't know when exactly this error started to throw)
P.S.S. there are no INSERTs or DELETEs in my code, only UPDATEs...
<<UPDATE>>
I've found what was the problem: if "DN" field has NULL value then after changing it, the auto-generated UPDATE Statement don't affect anything, obviously because "DN" is contained in a primary key and command builder didn't expect for primary key field to have NULL values(who ever would))), no surprise this engine is called "Paradox")))
that's why in
CommandBuilder.GetUpdateCommand().CommandText
in where clause for "DN" field there was this kind of pattern:
... WHERE ((REZ = ?) AND (DN = ?) AND ...
while nullable fields are described like this:
... AND ((? = 1 AND Price IS NULL) OR (Price = ?)) AND ((? = 1 AND Nmed IS NULL) OR (Nmed = ?)) AND ...
P.S.S.S. Hey, I can try to set UpdateCommand manually to fix this!)))
Here is how I've managed to set the UpdateCommand manually and even get SQL code for every UPDATE command that is being executed!(more or less)). It is very helpful while debugging - I can see what sql query failed to execute during DataAdapter.Update(DBDataSet) command.
public void Update(DataSet DBDataSet)
{
DataAdapter.RowUpdating += before_update;
DataAdapter.Update(DBDataSet);
}
public void before_update(object sender, EventArgs e)
{
//Convert EventArgs to OleDbRowUpdatingEventArgs to be able to use OleDbCommand property
System.Data.OleDb.OleDbRowUpdatingEventArgs oledb_e = (System.Data.OleDb.OleDbRowUpdatingEventArgs) e;
//Get query template
string cmd_txt = oledb_e.Command.CommandText;
//Modify query template here to fix it
//cmd_txt = cmd_txt.Replace("table_name", "\"table_name\"");
//fill tamplate with values
string cmd_txt_filled = cmd_txt;
foreach(System.Data.OleDb.OleDbParameter par in oledb_e.Command.Parameters)
{
string par_type = par.DbType.ToString();
string string_to_replace_with = "";
if (par.Value.GetType().Name == "DBNull")
{
string_to_replace_with = "NULL";
}
else
{
if (par_type == "Int32")
{
par.Size = 4;
string_to_replace_with=Convert.ToInt32(par.Value).ToString();
}
else if (par_type == "Double")
{
par.Size = 8;
string_to_replace_with=Convert.ToDouble(par.Value).ToString().Replace(",",".");
}
else if (par_type == "DateTime")
{
par.Size = 8;
/* In Paradox SQL queries you can't just specify the date as a string,
* it will result in incompatible types, you have to count the days
* between 30.12.1899 and the required date and specify that number
*/
string_to_replace_with = DateToParadoxDays(Convert.ToDateTime(par.Value).ToString("dd.MM.yyyy"));
}
else if (par_type == "String")
{
string_to_replace_with = '"' + Convert.ToString(par.Value) + '"';
}
else
{
//Break execution if the field has a type that is not handled here
System.Diagnostics.Debugger.Break();
}
}
cmd_txt_filled = ReplaceFirst(cmd_txt_filled, "?", string_to_replace_with);
}
cmd_txt_filled = cmd_txt_filled.Replace("= NULL", "IS NULL");
//Get query text here to test it in Database Manager
//System.Diagnostics.Debug.WriteLine(cmd_txt_filled);
//Uncomment this to apply modified query template
//oledb_e.Command.CommandText = cmd_txt;
//Uncomment this to simply run the prepared update command
//oledb_e.Command.CommandText = cmd_txt_filled;
}
public string ReplaceFirst(string text, string search, string replace)
{
int pos = text.IndexOf(search);
if (pos < 0)
{
return text;
}
return text.Substring(0, pos) + replace + text.Substring(pos + search.Length);
}
private static string DateToParadoxDays(string date)
{
return (Convert.ToDateTime(date) - Convert.ToDateTime("30.12.1899")).TotalDays.ToString();
}
In this code every time ShenasehSamapel is two equal values I get an exception that says field ShenasehSamapel is not the primary key:
"The variable name '#ShenasehSamapel' has already been declared.
Variable names must be unique within a query batch or stored
procedure."
Here is the code that generates the error:
private void btnDefineNewKala_Click(object sender, EventArgs e)
{
if (txtShenasehSamapel.Text != "" & txtKalaName.Text != "")
{
//Anbar.FildArray[0]= txtRadif.Text;
Anbar.FildArray [1]= txtShenasehSamapel.Text;
Anbar.FildArray[2] =txtKalaName.Text;
string strDefineKala = "insert into AnbarFava.dbo.DefineKala (ShenasehSamapel ,KalaName )" +
" values ( #ShenasehSamapel , #KalaName )";
//Anbar.AnbarCMD.Parameters.AddWithValue("#Radif", Anbar.FildArray[0]);
Anbar.AnbarCMD.Parameters.AddWithValue("#ShenasehSamapel", Anbar.FildArray[1]);
Anbar.AnbarCMD.Parameters.AddWithValue("#KalaName", Anbar.FildArray[2]);
Anbar.RunQuery(strDefineKala);
for (int Element = 0; Element <= Anbar.FildArray.Length - 1; Element++)
{ Anbar.FildArray[Element] = null; }
//txtRadif.Text = " ";
txtShenasehSamapel.Text = "";
txtKalaName.Text = "";
/**/
string strcmd = "select * from AnbarFava.dbo.DefineKala";
SqlDataAdapter thisDataAdapter = new SqlDataAdapter(strcmd, Anbar.strCNN);
DataTable thisDataTable = new DataTable();
thisDataAdapter.Fill(thisDataTable);
dgvDefineKala.DataSource = thisDataTable;
}
else
{
MessageBox.Show("لطفا تمام خانه ها را پر کنید", "خطا",
MessageBoxButtons.OK); }
}
You are reusing connections and commands across function calls, you have a parameter from a previous call conflicting with your current call.
Anbar.AnbarCMD should not exist, you should create a new command each time. I also assume Anbar also holds a SqlConnection object, it should not be doing that either. All Anbar should hold is a connection string and a new connection and new command should be created each Click (Be sure to put the command and connection inside using statements so they get disposed)
I don't know exactly what RunQuery is doing but it could be rewritten to something similar to
public void RunQuery(string query, params SqlParameter[] parameters)
{
using(var connection = new SqlConnection(_connectionString)
using(var command = new SqlQuery(query, connection)
{
connection.Open();
command.Parameters.AddRange(parameters);
command.ExecuteNonQuery();
}
}
You then call it like so
var param1 = new SqlParameter("#ShenasehSamapel", Anbar.FildArray[1]);
var param2 = new SqlParameter("#KalaName", Anbar.FildArray[2]);
Anbar.RunQuery(strDefineKala, param1, param2);
This is my second post. After learning from my first post how fantastic is to use Linq to SQL, I wanted to try to import data from a Excel sheet into my SQL database.
First My Excel Sheet:
it contains 4 columns namely
ItemNo
ItemSize
ItemPrice
UnitsSold
I have a created a database table with the following fields
table name ProductsSold
Id int not null identity --with auto increment set to true
ItemNo VarChar(10) not null
ItemSize VarChar(4) not null
ItemPrice Decimal(18,2) not null
UnitsSold int not null
Now I created a dal.dbml file based on my database and I am trying to import the data from excel sheet to db table using the code below.
Everything is happening on click of a button.
private const string forecast_query = "SELECT ItemNo, ItemSize, ItemPrice, UnitsSold FROM [Sheet1$]";
protected void btnUpload_Click(object sender, EventArgs e)
{
var importer = new LinqSqlModelImporter();
if (fileUpload.HasFile)
{
var uploadFile = new UploadFile(fileUpload.FileName);
try
{
fileUpload.SaveAs(uploadFile.SavePath);
if(File.Exists(uploadFile.SavePath))
{
importer.SourceConnectionString = uploadFile.GetOleDbConnectionString();
importer.Import(forecast_query);
gvDisplay.DataBind();
pnDisplay.Visible = true;
}
}
catch (Exception ex)
{
Response.Write(ex.Source.ToString());
lblInfo.Text = ex.Message;
}
finally
{
uploadFile.DeleteFileNoException();
}
}
}
// Now here is the code for LinqSqlModelImporter
public class LinqSqlModelImporter : SqlImporter
{
public override void Import(string query)
{
// importing data using oledb command and inserting into db using LINQ to SQL
using (var context = new WSDALDataContext())
{
using (var myConnection = new OleDbConnection(base.SourceConnectionString))
using (var myCommand = new OleDbCommand(query, myConnection))
{
myConnection.Open();
var myReader = myCommand.ExecuteReader();
while (myReader.Read())
{
context.ProductsSolds.InsertOnSubmit(new ProductsSold()
{
ItemNo = myReader.GetString(0),
ItemSize = myReader.GetString(1),
ItemPrice = myReader.GetDecimal(2),
UnitsSold = myReader.GetInt32(3)
});
}
}
context.SubmitChanges();
}
}
}
can someone please tell me where am I making the error or if I am missing something, but this is driving me nuts.
When I debugged I am getting this error
when casting from a number the value must be a number less than infinity
I really appreciate it
Some options:
Add a watch on myReader.GetValue(0), myReader.GetValue(1),
etc. to see what the source value is. Add a breakpoint on the line
that's throwing the error and see which value is causing the issue.
Change your object initializer to separate calls to see which column is throwing the error:
ProductSold product = new ProductsSold();
product.ItemNo = myReader.GetString(0);
product.ItemSize = myReader.GetString(1);
product.ItemPrice = myReader.GetDecimal(2);
product.UnitsSold = myReader.GetInt32(3);
context.ProductsSolds.InsertOnSubmit(product);
I have a form with a text box and button, such that when the user clicks the button, the specified name in the text box is added to a table in my sql database. The code for the button is as follows:
private void btnAddDiaryItem_Click(object sender, EventArgs e)
{
try
{
string strNewDiaryItem = txtAddDiaryItem.Text;
if (strNewDiaryItem.Length == 0)
{
MessageBox.Show("You have not specified the name of a new Diary Item");
return;
}
string sqlText = "INSERT INTO tblDiaryTypes (DiaryType) VALUES = ('" + strNewDiaryItem + "');";
cSqlQuery cS = new cSqlQuery(sqlText, "non query");
PopulateInitialDiaryItems();
MessageBox.Show("New Diary Item added succesfully");
}
catch (Exception ex)
{
MessageBox.Show("Unhandled Error: " + ex.Message);
}
}
The class cSqlQuery is a simple class that executes various T-SQL actions for me and its code is as follows:
class cSqlQuery
{
public string cSqlStat;
public DataTable cQueryResults;
public int cScalarResult;
public cSqlQuery()
{
this.cSqlStat = "empty";
}
public cSqlQuery(string paramSqlStat, string paramMode)
{
this.cSqlStat = paramSqlStat;
string strConnection = BuildConnectionString();
SqlConnection linkToDB = new SqlConnection(strConnection);
if (paramMode == "non query")
{
linkToDB.Open();
SqlCommand sqlCom = new SqlCommand(paramSqlStat, linkToDB);
sqlCom.ExecuteNonQuery();
linkToDB.Close();
}
if (paramMode == "table")
{
using (linkToDB)
using (var adapter = new SqlDataAdapter(cSqlStat, linkToDB))
{
DataTable table = new DataTable();
adapter.Fill(table);
this.cQueryResults = table;
}
}
if (paramMode == "scalar")
{
linkToDB.Open();
SqlCommand sqlCom = new SqlCommand(paramSqlStat, linkToDB);
this.cScalarResult = (Int32)sqlCom.ExecuteScalar();
linkToDB.Close();
}
}
public cSqlQuery(SqlCommand paramSqlCom, string paramMode)
{
string strConnection = BuildConnectionString();
SqlConnection linkToDB = new SqlConnection(strConnection);
paramSqlCom.Connection = linkToDB;
if (paramMode == "table")
{
using (linkToDB)
using (var adapter = new SqlDataAdapter(paramSqlCom))
{
DataTable table = new DataTable();
adapter.Fill(table);
this.cQueryResults = table;
}
}
if (paramMode == "scalar")
{
linkToDB.Open();
paramSqlCom.Connection = linkToDB;
this.cScalarResult = (Int32)paramSqlCom.ExecuteScalar();
linkToDB.Close();
}
}
public string BuildConnectionString()
{
cConnectionString cCS = new cConnectionString();
return cCS.strConnect;
}
}
The class works well throughout my application so I don't think the error is in the class, but then I can't be sure.
When I click the button I get the following error message:
Incorrect syntax near =
Which is really annoying me, because when I run the exact same command in SQL Management Studio it works fine.
I'm sure I'm missing something rather simple, but after reading my code through many times, I'm struggling to see where I have gone wrong.
you have to remove = after values.
string sqlText = "INSERT INTO tblDiaryTypes (DiaryType) VALUES ('" + strNewDiaryItem + "');"
and try to use Parameterized queries to avoid Sql injection. use your code like this. Sql Parameters
string sqlText = "INSERT INTO tblDiaryTypes (DiaryType) VALUES (#DairyItem);"
YourCOmmandObj.Parameters.AddwithValue("#DairyItem",strNewDiaryIItem)
Remove the = after VALUES.
You do not need the =
A valid insert would look like
INSERT INTO table_name (column1, column2, column3,...)
VALUES (value1, value2, value3,...)
Source: http://www.w3schools.com/sql/sql_insert.asp
Please use following:
insert into <table name> Values (value);
Remove "=", and also i would recommend you to use string.format() instead of string concatenation.
sqlText = string.format(INSERT INTO tblDiaryTypes (DiaryType) VALUES ('{0}'), strNewDiaryItem);"
I have defined the function in one class like
public static DataSet GetAllPrimaryKeyTables()
{
//An instance of the connection string is created to manage the contents of the connection string.
using(var sConnection = new SqlConnection(ConfigurationSettings.AppSettings["ConnectionString"]))
{
//To Open the connection.
sConnection.Open();
//Query to select the table_names that have PRIMARY_KEYS.
string selectPrimaryKeys = #"SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' AND TABLE_NAME <> 'dtProperties'
ORDER BY TABLE_NAME";
//Create the command object
using(var sCommand = new SqlCommand(selectPrimaryKeys, sConnection))
{
try
{
//Create the dataset.
DataSet dsPrimaryKeyTables = new DataSet("INFORMATION_SCHEMA.TABLE_CONSTRAINTS ");
//Create the dataadapter object.
SqlDataAdapter daPrimaryKeyTables = new SqlDataAdapter(selectPrimaryKeys, sConnection);
//Provides the master mapping between the sourcr table and system.data.datatable
daPrimaryKeyTables.TableMappings.Add("Table", "INFORMATION_SCHEMA.TABLE_CONSTRAINTS ");
//Fill the dataadapter.
daPrimaryKeyTables.Fill(dsPrimaryKeyTables);
//Bind the result combobox with non primary key table names
DataViewManager dsvPrimaryKeyTables = dsPrimaryKeyTables.DefaultViewManager;
return dsPrimaryKeyTables;
}
catch(Exception ex)
{
//Handles the exception and log that to the EventLog with the original message.
EventLog log = new EventLog("Application");
log.Source = "MFDBAnalyser";
log.WriteEntry(ex.Message);
return null;
}
finally
{
//checks whether the connection is still open.
if(sConnection.State != ConnectionState.Closed)
{
sConnection.Close();
}
}
}
}
}
And now how should i code so that I can call that function in another class in a dafault dataset.
Will anybody please help me??
Making this function an Extension Method on DataSet type will sole your problem if I understand you,
You will use something like this.
Dataset myPrimaryKeyDataset = YourClassName.GetAllPrimaryKeyTables();
Hope this helps.