I am currently attempting to write a .net 4.6 console app to work with a database, below is the test database structure and I have tried a number of tutorials in order to set about the best way to insert and update the data and what i seem to come up with seems somewhat cumbersome or not particularly manageable.
USE [Test_Table]
GO
INSERT INTO [dbo].[Test_Data]
([Identifier]
,[XDocument]
,[XVersion]
,[XSubVersion]
,[SubmittedBy]
,[SubmissionID]
,[SubmissionDateTime]
,[AssociatedFiles]
,[UpdatedXdocument]
,[DateTimeUpdated]
,[UpdateComments])
VALUES
(<Identifier, nvarchar(20),>
,<XDocument, xml,>
,<XVersion, int,>
,<XSubVersion, int,>
,<SubmittedBy, nvarchar(20),>
,<SubmissionID, nvarchar(20),>
,<SubmissionDateTime, datetime,>
,<AssociatedFiles, nvarchar(max),>
,<UpdatedXdocument, xml,>
,<DateTimeUpdated, datetime,>
,<UpdateComments, nvarchar(10),>)
GO
At the moment i am looking at this tutorial: https://sqlchoice.azurewebsites.net/en-us/sql-server/developer-get-started/csharp/win/step/2.html
However i would really like to know what the best/most professional way in order to insert and update data against this? as it I will seed some columns but then update later on, to date i have not needed to use sql data as yet so would really like to start with a good footing from experienced programmers.
my connection method is this which works great:
SqlConnection _sqlConnection;
SqlDataReader _sqlData;
SqlCommand _sqlCommand;
public bool ConnectToDB()
{
try
{
string conString = $"Data Source={TEST_Config.Database_Host};Initial Catalog={TEST_Config.Database_Name};Integrated Security={TEST_Config.Integrated_Security}";
_sqlConnection = new SqlConnection(conString);
_sqlConnection.Open();
return true;
}
catch(Exception CTDB_EX)
{
log.Info($"Issues Encountered Connecting to the Database: {CTDB_EX.Message}");
if (log.IsDebugEnabled)
{
log.Debug($"STACK_TRACE: {CTDB_EX.StackTrace}");
}
return false;
}
}
After this i ran through a number of tutorials but struggled with larger column sets and handling them in the best way, I then decided to create a class for the columns with getters and setters ie
public string _Identifier {get;set;}
etc etc
but at this point i stalled and decided to look for advice.
Many thanks in advance.
Try to add a .dbml file in your project, using this you could manage all the database related activities with drag and drop database objects. It uses LINQ for all database transaction (select, insert, update, delete).
Related
This may not actually be a code issue, but here goes...
My C# program reads a CSV file and builds an SQL Insert statement to insert all rows of the file into a table, so the Insert statement becomes:
Insert GHP_For_CMS (GroupId, EmployeeID, etc...) values (rec1_field1, rec1_field2, etc...), (rec2_field1, rec2_field2, etc...)
SQL runs flawlessly against a Sandbox/Dev db from a Dev Server. SQL crashes with a NullReference exception ("Object not set to an instance of an object") against the same Sandbox/Dev db from a Production server. The Dev server has Framework version 4.0.30319.18052, and the Production has Framework version 4.0.30319.18063.
I know I haven't given a lot of information here, but anyone have any ideas? Or at least ideas of something to check? I've been banging my head against this one for 3-4 days and nothing is rearing it's ugly head.
TIA!
The error happens on the 'ExecuteNonQuery' below...
string dbConnString = ConfigurationManager.ConnectionStrings[targetDatabase].ToString();
if (null != dbConnString)
{
using (SqlConnection dbConn = new SqlConnection(dbConnString))
{
if (dbConn != null)
{
SqlCommand cmd = new SqlCommand(m_sqlInserts.ToString(), dbConn);
dbConn.Open();
int rowsAdded = cmd.ExecuteNonQuery();
...
So the answer to the question (because I couldn't post more details and I really wanted to know of things to try): is that it's a simple Permissions issue with the account that is running the process not being able to insert records to the table. The comment that helped me get to that conclusion came from #cdonner (Thank you, again!) in wanting to see a stack trace. I realized that I could return a StackTrace in the console log instead of just the InnerException message and it (the SQL Error) was finally revealed.
I have a VSTO addin. Right now I am hard coding two dictionaries for development. They need to persist so I am going to use mssql. I have created the tables and all, so everything is done on that end. But I'm having some trouble getting a few things to work so I have a few questions:
First, is it possible to use Windows Forms in VSTO to create a CRUD form for the database tables? There are 2 tables and they aren't too long.
Next, when connecting with SqlConnection, the example connection strings I am seeing don't make any sense. Here is an example: tmpConn = new SqlConnection("server=(local)\\SQLEXPRESS;Trusted_Connection=yes"); I'm not sure how to make the connection string. Right now my db is a local mssql instance, but in the future it will be hosted on a local network server. It says SQLEXPRESS now, is that the same as mssql? If not how can I change it to mssql? How do I construct the correct string for mssql and how do I authenticate? Is it done in the connection string or somewhere else?
Next to Last, is there an easy way to query a database with 3 columns, ID (PK), domain, and dirname. And place domain and dirname into a dict where domain is the key and dirname the value, the ID is uneeded for this.
Here is what I have so far:
public void retrieveClient(SqlConnection conn)
{
try
{
using (conn)
{
SqlCommand command = new SqlCommand(
"SELECT ClientDirName, ClientEmailDomain FROM ClientTable;",
conn);
conn.Open();
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
string clientDir = reader.GetString(0);
string clientEmail = reader.GetString(1);
clientDict.Add(clientEmail, clientDir);
}
}
else
{
MessageBox.Show("No rows found in ClientTable", "Rows Not Found", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
reader.Close();
}
}
catch (InvalidOperationException ex)
{
MessageBox.Show(String.Format("Exception while accessing ClientTable: {0}", ex), "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (SqlException ex)
{
MessageBox.Show(String.Format("Exception while accessing ClientTable: {0}", ex), "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
And finally, the part where it says string clientDir = reader.GetString(0) and string clientEmail = reader.GetString(1) Will it return the correct values here? The table has 3 values as I said, ID, Dir, and Email. But as you can see my SqlCommand only selects ClientDirName and ClientEmailDomain. Does this mean the GetString() methods will return those with 0 and 1? Or would it be 1 and 2 since ID is 0? I'm not sure how it works, does reader.GetString() base the indexes off the actual table or the SqlCommand?
I also wanted to know if the while (reader.Read()) part will add each row one by one so that my clientDict.Add() would work properly or not.
If it possible to do CRUD with a database with windows forms please give me some guidance or a small example. Other than that I just need my code examined to make sure it's doing what I want. I've been trying to test it but there are a lot of other missing pieces at the moment so I need assistance.
Any assistance would be much appreciated. And if someone could provide a few small example connection strings for both local and network mssql servers that require authentication it would be a huge help. I've been looking everywhere and can't get this working. I've heard EF could do it but I can't find a single example or guide that does what I need. If someone could share one that may help too, if you with EF is the way to go.
Thanks in advance!
You may treat your VSTO based add-in as a regular .Net application. There is no anything specific from the Db perspective. The only difference is that your VSTO assembly is run within the host application (not standalone). So, I'd suggest reading any good book on how to use SQL databases (ADO.NET) in .net applications or use EF (Entity Frameworks) first. It will give you the answer to all your questions.
I'm writing an app in C# WPF with VS10 express.
I have to say I'm a very beginner in C# and VS but I'v searched a lot of examples on Google, I really tried to solve this problem on my own..
I have a local database (mydatabase.sdf) and at the load of my window I fill a table of that database with some data. One of the fields of that table needs a unique value, so I want to put in every load the same data, but I get an error than off course.
I want to delete all the data from the database before I refill, this seems to be so easy but I don't get it working...
I tried
dataset.Tables["mytable"].Clear()
that doesn't work, it seems to be deleting only data from the datagrid (dataTable) but not really from the datastore.
also I tried:
for (int i = 0; i < dataset.Tables["mytable"].Rows.Count; i++)
{
dataset.Tables["mytable"].Rows[i].Delete();
}
this.TableAdapter.Update(this.dataset);
But at startup the dataset.Tables["mytable"].Rows.Count statement returns zero at startup, but if I put in my data I get the "unique-value error".
The only way to get it deleted is to delete it manually from the datagrid and then push an Update button, that really deletes it from the datastore.
It is no option to make that field in the database not-unique because of development reasons.
How can I delete really data from the datastore/database (mydatabase.sdf) in the load of my program??
EDIT
Here is the code how I fill the database with data:
public void FillInternet()
{
klantenTableAdapter1.ClearBeforeFill = false;
string MyConString = "SERVER=myserver;" +
"DATABASE=mydb;" +
"UID=myuid;" +
"PASSWORD=mypass;";
MySqlConnection connection = new MySqlConnection(MyConString);
MySqlCommand command = connection.CreateCommand();
MySqlDataReader Reader;
command.CommandText = "SELECT klantnr, voorletters, roepnaam, achternaam, tussenvoegsel, meisjesnaam, straat, huisnr, subhuisnr, postcode, plaats, telthuis, telmobiel, telwerk, fax, email, geboortedatum FROM klanten ORDER BY klantnr";
connection.Open();
Reader = command.ExecuteReader();
try
{
while (Reader.Read())
{
DataRow newLogRow = dataset1.Tables["klanten"].NewRow();
var thisrow = "";
for (int i = 0; i < Reader.FieldCount; i++)
{
thisrow = Reader.GetValue(i).ToString();
newLogRow[Reader.GetName(i)] = thisrow;
}
dataset1.Tables["klanten"].Rows.Add(newLogRow);
this.klantenTableAdapter1.Update(this.dataset1);
}
connection.Close();
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message,"Fout",MessageBoxButton.OK,MessageBoxImage.Error);
}
dataset1.AcceptChanges();
//Fill from internet
//da.Fill(dataset1.klanten);
//Fill from local database
klantenTableAdapter1.Fill(dataset1.klanten);
this.klantenTableAdapter1.Update(this.dataset1);
this.DataContext = dataset1.klanten.DefaultView;
}
ADO.NET uses a "disconnected" recordset model. It keeps a copy of the data in client-side structures (DataSet and DataTable). Updates/inserts/deletions made to the client-side structures need to be pushed back out to the database. You need to read up on ADO.NET to get a basic understanding of this process and to get a sense of the ADO.NET event-model, which will be necessary if you want to do anything that involves typical real-world complications. There are many books written on ADO.NET because it is a feature-rich middle-tier data layer with significant complexities.
For your purposes, you could read up on the ADO.NET Command object and the SQL "delete" command. You will also need to explore how ADO.NET handles autoincrementing primary keys, which is one of the trickiest aspects of the disconnected model.
If the database itself defines an autoincrementing key, you cannot supply that value when inserting new rows unless you turn the auto-increment off temporarily in the back-end. That is not an ADO.NET issue, BTW. That is 100% back-end.
From your other posts, I'm going on the assumption that your database on this too is MySQL. You mention a unique column which typically means an auto-increment column. If you "delete" the entries after you've built them (say starting 1-10), and then try to re-add your next cycle the same 1-10 items, it can choke on you giving you this message. If you add numbers to your table starting with the last one used... see if that helps.
The Scenario:
I have a mobile phone comparing asp.net website which displays deals of various networks. The data about the deals we receive from the networks is in an excel sheet. We import the data from the excel sheets to the tables of each network in our database. Now, the data that we receive is not consistent for every network, as in, a network may name give the phone name as 'curve 8250' and another may give it as '8250 curve' and another might give it as '8250curve'.
Now, we have another module which allows the user to view the deals of a particular handset available on all the networks. To make this module work, what we need to do id make sure that the phone names are consistent for all the networks.
For this, I am planning to make a module for the webadmin which displays the phone names(probably in a gridview) from all the network tables, and the webmaster could edit the phone names so as to make them consistent. The retrieval of the distinct column names from all the tables was easy, and that is done.
The Problem:
Now, the real part is that how can we program the module so that it updates the particular column values in all the network tables. The schema of each table is exactly the same.
Edit: I always forget to add something :# . I know it can be done the hard way, in code behind, running a loop. But is there any simpler, hassle free way out there? like some datacontrol that would make life a bit easier in this situation?
Update:
I tried doing this using code behind. I made a gridview and displayed the data using item templates, and also provided a textbox in a second template. Then on a button click, I'm running this code:
protected void Button1_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(ConfigurationSettings.AppSettings[0].ToString());
foreach(GridViewRow gvr in GridView1.Rows)
{
TextBox tb = (TextBox)gvr.FindControl("New Value");
Label lbl = (Label)gvr.FindControl("Old Value");
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
if (lbl.Text != tb.Text)
{
try //updation if primary key constraint is not broken
{
con.Open();
cmd.CommandText = myupdatecommand; /*this is not the actual command that I'm passing, the command I'm passing does contain the values lbl.Text & tb.Text. This is just to make it a better read.*/
cmd.ExecuteNonQuery();
}
catch (SqlException sqe)
{
if (sqe.ErrorCode == -2146232060)//if primary key constraint is broken
{
try
{
//delete the row from the table that contains only unique phone names
cmd.CommandText = deletecommand;
cmd.ExecuteNonQuery();
}
catch { }
}
}
finally
{
con.Close();
}
//Update table2
try //only updation as here the phone name is not a primary key
{
con.Open();
cmd.CommandText = updatetable2;
cmd.ExecuteNonQuery();
}
catch
{
}
finally
{
con.Close();
}
.
.
.
//similarily update rest of the tables
.
.
.
Response.Redirect(Request.Url.ToString());
}
}
When I run the this code, everything happens smoothly, but when we update more than one row in the grid at a time, the updation only occurs for the first edited row, the other edited rows are remaining the same.
I know it must be a very small thing that I'm missing out on here, but I'm not able to proceed further :(
Any help on the matter is highly appreciated. Thanks in advance!
PS- I'm using ASP.Net 3.5, with c# as code behind, and SQL Server 2005 as back-end.
OK, I'm going to assume you are using LINQ-to-Sql, but in theory, it shuoldn't matter, the basic principle is the same.
You will need a collection of connection string, one for each each database. Presumably you already have this.
using (TransactionScope scope = new TransactionScope())
{
foreach (var connStr in listOfConnStr)
{
using (var db = new MyDataContext(connStr);
{
// do update here.
}
}
}
That's pretty much it.
You could pass the "do update here" part in as a lambda function.
To be honest, I'm now embarrassed to answer my own question.
The problem was just that I had mistakenly put the Response.Redirect(Request.Url.ToString());
inside the if loop which itself is inside the foreach loop.
When will I stop doing silly mistakes :|
In short: What is a good method for setting up read-only data access from Silverlight to a MySQL database?
Here are the details of my situation:
I'm currently trying to set up a Silverlight application to present data from a MySQL database. Currently, I need to set-up read-only access to the MySQL database (I may set up other tables for complete CRUD functionality at a later, date, but for these particular tables, I'm only ever going to be concerned with the retrieve aspect).
I tried setting it up using RIA Services (CTP July 2009) with Entity Framework, but I had trouble debugging it and ended up trying to recompile the source code from the MySQL ADO.NET connector in order to install custom DLLs into the GAC. I wasn't able to get any of this stuff to work correctly.
My problem was that I had date values stored as 0000-00-00 in lots of my MySQL tables. The MySQL ADO.NET Connector throws an exception everytime it tries to bring down a row with an invalid date in it. I would try to recompile the connector (see links above), but that's feeling very much like a hack. I would try to update the values in the MySQL database to be within the appropriate spec for dates, but our IT manager (and effectively our DBA) does not want to do it.
I don't mind learning to work with LINQ (LINQ-to-what?), but I want to avoid concatenating my own strings of SQL commands. Because of the Date restrictions, I need a way to specify Case When orders.OrderDate = '0000-00-00' Then '0001-01-01' Else orders.OrderDate End for pretty much every date instance.
I'm especially interested to hear from folks who have worked with .NET and MySQL together. What will work in my situation?
Why has no one suggested using a ORM to hide the mySQL details? Both NHibernate and Subsonic support mySQL. Both are very customisable in how they interact with the database and should allow you to cater for malformed dates.
By using an ORM your data objects are now POCOs, and you can use whatever you want to get the data to the Silverlight client. Vanilla web services or WCF should be fine. RIA services if you want to try out the bleeding edge.
IMHO, this will be simpler than setting up a mysql->php->xml->asp.net->silverlight chain.
My problem was that I had date values stored as 0000-00-00 in lots of my MySQL tables.
Can you just write Select NullIf( SomeDate, '0000-00-00') As SomeDate From SomeTable in your SQL queries? I don't know MySQL, but that's what I would do in T-SQL.
Here is what I did for a similar problem I was facing.
I used php to get data from the MySQL database and turned it into an XML file. I called that file from my silverlight app and used LINQtoXML to parse the data and make it available in my XAML controls. I am not a programmer by trade so maybe there is a better way to do it but this works for my app. Hope this helps. LINQ ROCKS!
Here is a portion of the code:
< ?php
header("Content-type: text/xml");
$grb_hostname = "host";
$grb_database = "dbName";
$grb_username = "dbUser";
$grb_password = "dbPwd";
$grb = mysql_connect($grb_hostname, $grb_username, $grb_password);
mysql_select_db($grb_database, $grb);
$results = mysql_query("SELECT * FROM bursts ORDER BY bursts.id DESC");
$xmlOutput = "<?xml version=\"1.0\"?>\n";
$xmlOutput .= "<grbs>\n";
while($row = mysql_fetch_array($results)) {
$xmlOutput .= "\t<grb id=\"".$row['id']."\" trigger=\"".$row['trigger']."\">\n";
$xmlOutput .= "\t\t<grb_id>".$row['grb_id']."</grb_id>\n";
$xmlOutput .= "\t\t<burst_ra>".$row['burst_ra']."</burst_ra>\n";
$xmlOutput .= "\t\t<burst_dec>".$row['burst_dec']."</burst_dec>\n";
$xmlOutput .= "\t</grb>\n";
}
$xmlOutput .= " < /grbs>"; // no space before /
echo $xmlOutput;
?>
then in my Silverlight I have the following:
private void LoadGrbs()
{
WebClient grbXmlFile = new WebClient();
// Make sure the crossdomainpolicy.xml file exists on the remote server.
grbXmlFile.DownloadStringAsync(new Uri("url_xml_generating_php_file", UriKind.Absolute));
grbXmlFile.DownloadStringCompleted += new DownloadStringCompletedEventHandler(grbsXmlLoaded);
}
private void grbsXmlLoaded(object sender, DownloadStringCompletedEventArgs e)
{
processGrbXml(e.Result);
}
private void processGrbXml(string grbData)
{
XDocument grbs = XDocument.Parse(grbData);
var query = from g in grbs.Descendants("grb")
select new
{
grbId = (string)g.Element("grb_id"),
grbDec = (string)g.Element("burst_dec")
};
foreach (var grb in query)
{
grbListbox.Items.Add(grb.grbId);
}
}
grbListbox is a Listbox control in my Silverlight app.
You should use RIA Services, the newest version came out last week, and it's included in the silverlight 4 beta now.
http://silverlight.net/getstarted/silverlight-4-beta/
You don't have to use the entity framework with RIA, there are other options. We do, but we use SQL Server so that might not be your favorite.
They have changed the errors some in the new RIA Stuff, so I'd recommend taking a 2nd look. Here's Brad Abrams' example from last week:
http://microsoftpdc.com/Sessions/CL21
Finally, if you're having a lot of trouble debugging, you could take a look at Fiddler. It's a program that watches the traffic and it can display you the errors you're having in a more obvious fashion.