I have a database containing one table with several columns, first of which is the auto generated ID.
I've created a dataset (.xsd) from it, and I'm trying to use it for reading, writing into and updating the database.
So far, reading works fine, all I have to do is:
var reservations = new DataSet1.reservationsDataTable();
var ta = new DataSet1TableAdapters.reservationsTableAdapter();
ta.Fill(reservations);
for (int i = 0; i < reservations.Rows.Count; i++)
{
// read whatever I need here...
}
However, when I try updating my database with these lines, it fails and it doesn't create a new record in my database:
var ta = new DataSet1TableAdapters.reservationsTableAdapter();
ta.Insert(LastName,Arrival,Departure);
Of course, I previously initialize variables LastName, Arrival and Departure with the user input. I also tried creating a new Insert query, but same thing happens, even worse - it wants a string type of input for a DateTime (Arrival, Departure).
I'm not sure what I'm doing wrong...
P.S - I also need to UPDATE my database using datasets later, so I really need to figure this out.
Thank you!
Related
I'm struggling to find a valid answer to what I'm trying to find.
Basically, I want to check if for example:
"tableNO1" exists or if every other table exists...
By the way, I'm using Access 2002-2003 if that somehow helps :)
Do you think I should upgrade to the latest version?
Background:
I'm trying to create run-time buttons that each one of them has a DB table, and when I close my program the tables that I created for each run-time created button will be saved. After I launch the program again I should click a button that will add these buttons that have DB tables (Each one of them has a dedicated table). for example, if 9 run-time buttons were created in the program before - each of them will have a DB table. I will have a max 9 button and each of them will be named tableNO(n) n=number of table
when I click the button that creates run-time buttons for the first time, it will create a button called "tableNO1", the second time "tableNO2" will be created, and so on...
Thanks in advance.
Ok, there are several ways to do this, but I suggest this code:
public Boolean TableExist(string sTable)
{
using (OleDbConnection conn = new OleDbConnection(Properties.Settings.Default.AccessDB2))
{
conn.Open();
string[] sRestrict = new string[] {null,null,null,null};
sRestrict[2] = sTable;
DataTable MySchema = new DataTable();
MySchema = conn.GetSchema("Columns",sRestrict);
return (MySchema.Rows.Count > 0);
}
}
The above is also how you can get the schema (table def) as a table.
Thus, say
if (TableExist("tblHotels")
{
// your code here
}
Now, because you are possible (likely) using a loop, then you might consider for reasons of performance to pass a valid connection to the TableExist function, and thus for your loop not re-create a connection each time - as that will slow things down quite a bit.
Note that "many" often suggest doing this:
SELECT * FROM MSysObjects WHERE [Name] = 'tableNO1' AND Type = 1
The problem with above is by default, the MySysObjects requires elevated rights. The database can be opened, and then using security settings in access the rights to MySysOjbects can be changed - but it more work then the above code/function.
I have DataGridView where I am showing data read from database:
DataSet ds = new DataSet();
sqlDa.Fill(ds);
dgView.DataSource = ds.Tables[0]
After adding all of the rows in the UI, I need to to SQL UPDATE of rows that previously read from database, and do INSERT for new rows by clicking Save button (I don't save rows one by one when adding, just all of them when I click the Save button):
foreach (DataGridViewRow dgvRow in dgView.Rows)
{
// do insert for new rows, and update for existing ones from database
}
How can I know what rows are newly added and what are not? Can I add some type of attribute to every row that is read from database so that can I know that they need to be updated?
How can I know what rows are newly added and what are not?
You don't need to; the datatable the DGV is showing is already tracking this. If you make a SqlDataAdapter and plug a SqlCommandBuilder into it see the example code in the docs so that it gains queries in its InsertCommand/UpdateCommand/DeleteCommand properties (or you can put these commands in yourself, but there isn't much point given that a command builder can make them automatically) then you just say:
theDataAdapter.Update(theDataTable);
If you didn't save it anywhere else you can get it from the DataSource of the DGV:
theDataAdapter.Update(dgView.DataSource as DataTable);
Ny the way, the word "Update" here is nothing to do with an update query; Microsoft should have called it SaveChanges. It runs all kinds of modification query (I/U/D) not just UPDATE
If you really want to know, and have a burning desire to reinvent this wheel, you can check a DataRow's RowState property, and it will tell you if it's Added, Modified or Deleted, so you can fire the appropriate query (but genuinely you'd be reimplementing functionality that a SqlDataAdapter already has built in)
All this said, you might not be aware that you can make your life massively easier by:
Add a new DataSet type of file to your project (like you would add a class). Open it
Right-click in the surface of it, choose add TableAdapter
Design your connection string in (once)
Enter your query as a "select that produces rows" like SELECT * FROM SomeTable WHERE ID = Id (it's advisable to use a where clause that selects on the ID; you can add more queries later to do other things, like SELECT * FROM SomeTable WHERE SomeColumn LIKE #someValue but for now selecting on ID gives you a base query to use that is handy for loading related data). You can also use existing or new stored procs if you want
Give it a sensible name pair like FillById, GetDataById - FillBy fills an existing table, Get gets a new one
Finish
You'll now have objects available in your code that are wrappers data adapters and datatables - same functionality but more nicely strongly typed
e.g. you can fill your grid with:
var ta = new SomeTableAdapter();
dgView.DataSource = ta.GetDataByFirstName("John%"); //does select * from table where firstname like 'john%' into a datatable
The datatables are strongly typed, so you don't access them like this:
//no
foreach(DataRow row in someTable.Rows){
if((row["someColumn"] as string) == "hello" && row.IsNull("otherColumn"))
row["otherColumn"] = "goodbye";
}
You have named properties:
//yes
foreach(var row in someTable){
if((row.SomeColumn == "hello" && row.IsOtherColumnNull())
row.OtherColumn = "goodbye";
}
Much nicer. LINQ works on them too, without AsEnumerable or Cast and endless casting the values.
It's not magic; VS writes boatloads of code behind the scenes for you - check in the YourDataSet.Designer.cs file - hundreds of SqlCommands, fully parameterized, for all the table operations (Select/Insert/Update/Delete), all base don typing a SELECT command into a tool pane. It's quite nice to use really, even all these years later.
Oh, but the designer doesn't work very nicely in net core. They're really lagging behind on fixing up the bugs that netcore brings (other priorities)
I am trying to test different queries on a dataset from an existing Sql Server DB. I need to be able to grab a row by its id column for the project I am doing. What seems like a straightforward query gets no results however.
DataSet prodspdata = new prodspDataSet();
DataRow[] load;
load = prodspdata.Tables["TripNumber"].Select("[ctripnumber] = '21605178'");
Console.WriteLine(load.Length);
Console.ReadLine();
Output from load.Length is 0. I understand from documentation that load should be an array of rows returned from the Select() query. I know that this result exists from looking in the data so I expect load.length to be 1.
I tested a query from within Sql Server Management Studio to make sure I wasn't missing something:
SELECT * FROM TripNumber WHERE ctripnumber = '21605178'
This returns the 1 row as expected.
Is my Select query bad? I am brand new to C#, am I testing it wrong? I simply need to know if load contains any results so I know that my query works as intended.
EDIT: So it appears my DataTable has no rows.
DataTable loadTable;
loadTable = prodspdata.Tables["TripNumber"];
Console.WriteLine(loadTable.Rows.Count);
Console.ReadLine();
This returns 0 rows whereas loadTable.Columns.Countgives me 133
Did I miss a step, perhaps something to do with a TableAdapter?
Don't use the square brackets in your filtering.
load = prodspdata.Tables["TripNumber"].Select("ctripnumber = '21605178'");
Also remember that you can use Visual Studio debugger to see the contents of DataSets and Datatables.
I had not actually filled my dataset with anything, which was causing the problem. I severely neglected the TableAdapter. The code I added was:
prodspDataSetTableAdapters.TripNumberTableAdapter ta = new prodspDataSetTableAdapters.TripNumberTableAdapter();
DataTable loadTable = ta.GetData();
So without a TableAdapter instantiated and a table filled with the data (based on the TableAdapter's settings) you basically get an empty schema of the database with tables, columns and no values. Rookie mistake.
I've a WPF situation with one page that has a datagrid with clients, and another page with field to fill in a new client.
I want the "new-client-page" to search the highest clientID en increment that with 1 for the new client, this sounds very simple, but I've a problem with it.
In the table adapter of the table, I added a new query: SELECT MAX(clientID) FROM clients
I execute the query with:
DataSet1TableAdapters.klantenTableAdapter tableAdapter = new DataSet1TableAdapters.klantenTableAdapter();
DataSet1 datasetvar = new DataSet1();
int returnValue = (int)tableAdapter.GetMaxKlantnr();
This works fine once. I get the highest value in returnValue, but if I go for the second time to the "new-client-page", the clientID is still the same..
I tried to update the dataset with tableAdapter.Update(datasetvar); but that doesnt make sense.. :(
Lars what database are you using? Set the ID column as identity and it will be auto generated by the db, your solution would not support any concurrency anyway and it's not the way to go to read the max id and add 1 to it...
You need to set it when you add a new row. It is then executed as an INSERT by the adapter. Adapters commit only changes.
The code would look almost like:
var newRow = ClientTable.NewRow();
newRow["ClientID"] = GetNewID();
...set other fields...
ClientTable.Rows.Add(newRow);
Adapter.Update(ClientTable);
Hey guys, I'm having a weird time with Linq-To-SQL
I'm building a postit system that allows people to make postits and attach them to multiple objects. The database for this is a table that has the postits themselves (id, message, etc) and a linkstable which holds the records to which a postit is attached.
the weird thing I'm experiancing is the following.
When I retrieve an object from the database (using Linq-To-SQL), do some data changing and submit it again, I experience no trouble whatsoever.
Yet, when I try to make a new one I get an exception in the Submitchanges method in the datacontext: Specified Cast is not valid.
I've been looking on the web and mostly it involves some change in the mapping, but this shouldn't be the case as I can update without any problems.
T_PostIt np = new T_PostIt();
np.CreatedOn = DateTime.Now;
np.CreatedBy = Request.ServerVariables["REMOTE_USER"].ToString();
np.MarkedForDeletion = false;
np.Message = txtNewPostitMessage.Text;
np.ModifiedBy = Request.ServerVariables["REMOTE_USER"].ToString();
foreach (int i in ServerIds)
{
T_PostIt_Link pil = new T_PostIt_Link();
pil.LinkType = 'S';
pil.LinkID = i;
pil.MarkedForDeletion = false;
np.T_PostIt_Links.Add(pil);
}
dc.T_PostIts.InsertOnSubmit(np);
dc.SubmitChanges();
I use the above code and can't seem to get what I'm doing wrong.
help anyone?
Have you tried updating the properties one by one, and then save the changes back to the database? It could be that updating the entity only fails when one specific value has changed. If I may guess, it could be that the value of CreatedOn cannot be cast to a valid DateTime in the database (due to culture settings). That would explain why updating goes OK - you're not changing the value of CreatedOn here. You do, however, when inserting a new entity.
Edit: maybe this is the problem you're facing. Also, be sure to read this thread, where the topic starter eventually points to the first thread mentioning that it is an apparant bug in Linq2Sql.