I created a service-based local db via Visual Studio 2013 Express edition.. The connection string, dataset and TableAdapter were added automatically.
On click of a button, I am trying to insert some data by calling TableAdapter.Insert
As it is I already have a dataGridView's datasource bound to the dataset, So I immediately see that the data was inserted in table properly at run time, But when I close the application, The actual DB dosn't contain the data. Therefore, The data isn't actually inserted in DB.
According to http://msdn.microsoft.com/en-us/library/ms233812%28v=vs.110%29.aspx
With insert, you have to only call insert, yet I am calling Update and AcceptChanges on table, for safety, well I tried the first way shown in link (i.e. creating a row and adding it to dataset then calling update) as well, but it seems the data isn't being inserted in DB at all.
Finally, the insert code, rds is DataSet and ta is TableAdapter
private void AddBtn_Click(object sender, EventArgs e)
{
ta.Insert("foo", "bar", 2, "zing", "tada");
ta.Fill(rds.reminders);
rds.reminders.AcceptChanges();
ta.Update(rds.reminders);
}
It turned out that, as I was using the VS compiled application each time the mdf database was being overwritten, hence the changes I made were completely erased,
The possible solution could be one of following
1)Change the connectionstring to point to database that is in Debug folder, which wont be overwritten each time you compile and run the application
2)You could simply let the connectionstring be as it is and just test it through detached compiler mode.
I was able to figure this out due to the following stackoverflow link I suddenly sumbled upon after 2 days.
Database changes do not persist after ObjectContext.SaveChanges() is called
ClearBeforeFill Property
http://msdn.microsoft.com/en-us/library/bz9tthwx.aspx
"By default, every time you execute a query to fill a TableAdapter's
data table, the data is cleared and only the results of the query are
loaded into the table."
Related
The more I read on this, the more confused I get, so hope someone can help. I have a complex database setup, which sometimes produces the error on update:
"Concurrency violation: the UpdateCommand affected 0 of the expected 1 records"
I say sometimes, because I cannot recreate conditions to trigger it consistently. I have a remote mySQL database connected to my app through the DataSource Wizard, which produces the dataset, tables and linked DataTableAdapters.
My reading suggests that this error is meant to occur when there is more than one open connection to the database trying to update the same record? This shouldn't happen in my instance, as the only updates are sequential from my app.
I am wondering whether it has something to do with running the update from a background worker? I have my table updates in one, for example, thusly:
Gi_gamethemeTableAdapter.Update(dbDS.gi_gametheme)
Gi_gameplaystyleTableAdapter.Update(dbDS.gi_gameplaystyle)
Gi_gameTableAdapter.Update(dbDS.gi_game)
These run serially in the backgroundworker, however, so unsure about this. The main thread also waits for it to finish, and there are no other db operations going on before or after this is started.
I did read about going into the dataset designer view, choosing "configure" in the datatableadapter > advanced options and setting "Use optimistic concurrency" to false. This might have worked (hard to say because of the seemingly random nature of the error), however, there are drawbacks to this that I want to avoid:
I have around 60 tables. I don't want to do this for each one.
I sometimes have to re-import the mysql schema into the dataset designer, or delete a table and re-add it. This would obviously lose this setting and I would have to remember to do it on all of them again, potentially. I also can't find a way to do this automatically in code.
I'm afraid I'm not at code level in terms of the database updates etc, relying on the Visual Studio wizards. It's a bit late to change the stack as well (e.g. can't change to Entity Framework etc).
SO my question is:
what is/how can I find what's causing the error?
What can I do about it?
thanks
When you have tableadapters that download data into datatables, they can be configured for optimistic concurrency
This means that for a table like:
Person
ID Name
1 John
They might generate an UPDATE query like:
UPDATE Person SET Name = #newName WHERE ID = #oldID AND Name = #oldName
(In reality they are more complex than this but this will suffice)
Datatables track original values and current values; you download 1/"John", and then change the name to "Jane", you(or the tableadapter) can ask the DT what the original value was and it will say "John"
The datatable can also feed this value into the UPDATE query and that's how we detect "if something else changed the row in the time we had it" i.e. a concurrency violation
Row was "John" when we downloaded it, we edited to "Jane", and went to save.. But someone else had been in and changed it to "Joe". Our update will fail because Name is no longer "John" that it was (and we still think it is) when we downloaded it. By dint of the tableadapter having an update query that said AND Name = #oldName, and setting #oldName parameter to the original value somedatarow["Name", DataRowVersion.Original].Value (i.e. "John") we cause the update to fail. This is a useful thing; mostly they will succeed so we can opportunistically hope our users can update our db without needing to get into locking rows while they have them open in some UI
Resolving the cases where it doesn't work is usually a case of coding up some strategy:
My changes win - don't use an optimistic query that features old values, just UPDATE and erase their changes
Their changes win - cancel your attempts
Re-download the latest DB state and choose what to do - auto merge it somehow (maybe the other person changed fields you didn't), or show the user so they can pick and choose what to keep etc (if both people edited the same fields)
Now you're probably sat there saying "but noone else changes my DB" - we can still get this though, if the database has changed some values upon one save and you don't have the latest ones in your dataset..
There's another option in the tableadapter wizardd - "refresh the dataset" - it's supposed to run a select after a modification to import any latest database calculated values (like auto inc primary keys or triggers/defaults/etc). Some query like INSERT INTO Person(Name) VALUES(#name) is supposed to silently have a SELECT * FROM PERSON WHERE ID = last_inserted_id() tagged on the end of it to retrieve the latest values
Except "refresh the dataset" doesn't work :/
So, while I can't tell you exactly why youre getting your CV exception, I hope that explaining why they occur and pointing out that there are sometimes bugs that cause them (insert new record, calculated ID is not retreieved, edit this recent record, update fails because data wasn't fresh) will hopefully arm you with what you need to find the problem: when you get one, keep the app stopped on the breakpoint and inspect the datarow: take a look at the query being run and what original/current values are being put as parameters - inspect the original and current values held by the row using the overload of the Item indexer that allows you to state the version you want and look in the DB
Somewhere in all of that there will be the mismatch that explains why 0 records were updated - the db has "Joe" as the name or 174354325 as the ID, your datarow has "John" as the original name or -1 as the ID (it never refreshed), and the WHERE clause is finding 0 records as a result
Some of your tables will contain a field that is marked as [ConcurrencyCheck] or [TimeStamp] concurrency token.
When you update a record, the SQL generated will include a WHERE [ConcurrencyField]='Whatever the value was when the record was retrieved'.
If that record was updated by another thread or process or something other than the current thread, then your UPDATE will return 0 records updated, rather than the 1 (or more) that was expected.
What can you do about it? Firstly, put a try/catch(DbConcurrencyException) around your code. Then you can re-read the offending record and try and update it again.
I have a .net winforms application which is using SQLite DB and I am using System.Data.SQLite dll.
This is how I load a Datatable:
DataTable table = new DataTable();
SQLiteDataAdapter m_readingsDataTableDataAdapter;
SQLiteCommandBuilder m_readingsDataTableCommandBuilder;
m_readingsDataTableCommandBuilder = null;
m_readingsDataTableDataAdapter = null;
// Create fresh objects
m_readingsDataTableDataAdapter = new SQLiteDataAdapter(sql, Database.getInstance().connectionObj);
m_readingsDataTableCommandBuilder = new SQLiteCommandBuilder(m_readingsDataTableDataAdapter);
m_readingsDataTableDataAdapter.Fill(table);
return table;
This data table has one primary key and no other constraints.
I set it as a data source for DataGridView and after all the edits, I update the DataTable like this:
m_readingsDataTableDataAdapter.Update(table);
Occasionally, the updates fires an error and I don't know when, it stops throwing errors - probably after system restart ( not sure ). And then, the updates go fine until another situation where this update throws an error again. When the error occurs, it happens for all updates from then on even after application restart.
Error:
An unhandled exception of type 'System.Data.DBConcurrencyException' occurred in System.Data.dll
Additional information: Concurrency violation: the UpdateCommand affected 0 of the expected 1 records.
I would appreciate any help or questions as this is quite a critical section of my project.
Thanks.
Update:
Based on suggestions, to ensure no other part of the program is editing the row, I loaded the DataTable, updated the row immediately and updated it as per the following code. And I still got the error. There is no other program running on my machine so the row is not updated by any other program except my application:
DataTable table = new DataTable();
SQLiteDataAdapter m_readingsDataTableDataAdapter;
SQLiteCommandBuilder m_readingsDataTableCommandBuilder;
m_readingsDataTableCommandBuilder = null;
m_readingsDataTableDataAdapter = null;
// Create fresh objects
m_readingsDataTableDataAdapter = new SQLiteDataAdapter(sql, Database.getInstance().connectionObj);
m_readingsDataTableCommandBuilder = new SQLiteCommandBuilder(m_readingsDataTableDataAdapter);
m_readingsDataTableDataAdapter.Fill(table);
// Update immediately
table.Rows[0]["RS485_ADDRESS"] = "400";
m_readingsDataTableDataAdapter.Update(table); // - Still throws error
return table;
I had a similar issue that drove me nearly mad. I even debugged into System.Data.SQLite . My issue was caused by the dynamic typing of SQLite:
Dynamic typing means that the column type is just a hint for the type of the stored value but not an enforcement. Here is what happened in my application: An integer column contained an empty string. Fetching the data triggered an implicit conversion to the column type so the empty string was converted to zero. The DbDataAdapter used this zero value in the WHERE clause of an UPDATE or DELETE statement which failed miserably because the conversion of zero to a string is not an empty string. I changed the affected integer columns to contain NULL and everything is fine now.
The sad fact about that: It is not a bug in SQLite or ADO.NET . DbAdapter and DbCommandBuilder expect strong typing and SQLite doesn't provide that by design.
I've seen this problem, it seemed to appear in some cases and not others. I have resolved it a different way. Since this is primarily a data issue, it involves changing the update and delete statements. There may be cases where your code might need to be validated, I'm not referring to those cases, this is for when all else seem to be in order and "Concurrency Violation" persists. And a good starting place before you spend hours debugging is to address how the updates are handled.
Open the Data Set Designer.
Click on the Table Adapter.
In the properties, expand the UpdateCommand
Edit the SQL so the Where-Clause refers only to the primary-key.
Example: Suppose the column EmployeeID is the primary-key in our table
Change to:
update ..... WHERE EmployeeID=#EmployeeID
By default it's usually constructed as:
update ... where ID=#ID AND col1=#col1 AND col2=#col2 AND col3=#col3
The where-clause is formed with all the columns to handle multi-user updates, to enforce an implicit concurrency. So if one user has a copy of the record, and another user updates that version by the time the first user updates it, first user's version is not current. Otherwise, primary-keys should be used to refer to a specific record.
But, this is an update/delete policy decision that the development and database teams need to coordinate. For a single developer/dba in-one, have a little meeting with yourself. Don't take the Microsoft where-clause without your review and understanding and explicit implementation. Need to specifically address what happens when 2 users have a copy of the same record, both from the application and database levels. Database "Transaction Isolation" Levels in SQL Server is a way to address it. ADO, ADO.NET, OLE DB, ODBC all have isolation level settings. More on SQL Server Transactions and isolation levels
In some cases multiple users are not involved, or the application is updating internally, concurrency is fully controlled, where-clause can be formed with the primary-key.
In my case, the update is done without a user involvement, so it makes sense to use the primary key. If you understand the reasoning and the cause of the behavior, it's a matter of adjusting to fit your environment.
I'm using a DataSet with the DataSet designer on xsd file (System.Data v 4 in VS 2015). I've been searching for how to get the ID for a newly created record. I see on the designer advanced options there is an option for reading back the record for insert and updates. I also see the SELECT included in the INSERT INTO statement. However the designer generated code runs ExecuteNonQuery and returns the number of records affected. How do we get access to that record that was read back in?
Most solutions I've read involve creating your own query or sp that is set to ExecuteScalar and selects the ##ROWIDENTITY. Either that or timestamp the new record and get it back that way. But if the read-back is already being done then I should be able to get to it, right? What' the trick? What happens to that data that's been read back in?
TIA,
Mike
SOLVED
I have problems with Linq to SQL inserting/updating/deleting dataset from table with stored procedures.
I have checked data connections, points on the same table that has been created when adding connection
I'm using Linq-to-Sql classes designer for managing behavior of sprocs for my tables (insert, update, delete)
I have same app created with different code style and everything works just fine but i can't include location change (when someone else installs app) in my .cs files, so I want to do it on "right way" and make it work for everyone.
using sql server 2012 and vs2010
Here is my problem.
this is included in form as reference for DataContext
private ZavrsniradDataContext poziv = new ZavrsniradDataContext();
//I've tried without private, and including this into methods where I'm using it and nothing.
after I declare some variables for sending it to sproc I call sproc for altering the table..
poziv.p_IzmjenaMjesta(#ID, #Naziv, #PP, #IDZupanije);
poziv.SubmitChanges();
note: I'm sending ID number of the dataset I want to change, for comparison..
Alter proc [dbo].[p_IzmjenaMjesta]
#ID int,
#Naziv varchar(30),
#PP int,
#IDZupanije int
.
.
.
Update Mjesto
SET Naziv= #Naziv, PostanskiPretinac = #PP, IDZupanije = #IDZupanije
WHERE ID = #ID;
After I call the sproc, my table is being refreshed, and all changes are visible. But after a while, all changes dissapear. I believe all my sprocs and functions are working properly, with my table, but somehow I'm doing something wrong. everything works perfecrly when I run sprocs in Management studio.
My other app contains this definition in beggining of the form, and everything works perfectly. updateing, inserting, deleting! But i don't want that solution because then I have to create fixed location for my database on every PC. I just want to install it and run it :)
public partial class Mjesta : Form
{
ZavrsniRad poziv;
public Mjesta()
{
InitializeComponent();
poziv = new ZavrsniRad(#"c:\zavrsni_rad\Zavrsni rad.mdf");
}
NOTE:
I'm using exact copy of both databases on different locations with same sprocs/functions/dataset for different apps, and one is working, the other one is not working.
and that grinds my gears :(
I have solved it.
app is running and working properly...
I forgot on that little thing :(
Problem solver, add all rights on modifying your database to every account you have.
That also includes rights to log file.
(i dont have rep points for posting pics)
http://www.pohrani.com/f/v/AQ/2bPLiVcP/slika.jpg
I am trying to insert a record into a table using an Entity Framework. I made my database (mdf file), made a model from the database (edmx), and now I am trying to insert a record.
Users Brad = new Users
{
UserInitials="BCH",
UserName="Brad"
};
using (WeighProgramDatabaseEntities wDB = new WeighProgramDatabaseEntities())
{
wDB.Users.AddObject(Brad);
int res = wDB.SaveChanges(System.Data.Objects.SaveOptions.AcceptAllChangesAfterSave);
List<Users> lwt = wDB.Users.ToList(); //call to look at the inserted data
}
When I follow this procedure it appears everything works fine. My wDB.Users.ToList(); returns one record which is the one I just inserted. However, if I run my code again, removing the insert stuff and just call the query (leaving just) List<Users> lwt = wDB.Users.ToList(); my query returns no records. What should I be doing differently to get my changes to persist? Why did my records "go away"?
WeighProgramDatabaseEntities inherits from ObjectContext.
This is my first attempt at using EF stuff so some of my verbiage might not be correct and I might not have included something important - let me know.
Edit:
I think my problem is that my Insert/Update/Delete functions are not mapped. But I'm not sure how to create a stored procedure for them to map to...
Edit2:
Ok, phew, I figured out the stored procedure mapping. and now that I have an INSERT mapped, and I call AddObject it will actually be inserted.
A little more complicated than I would have expected. For example if I right click on a table in my Database Explorer and select New Query it brings me to a great query designer window which let's me create Inserts, Selects, Updates... but there is no Save button! It's grey out. I need to write them from another route with does not let me generate Inserts/Deletes/Updates via a GUI. Which is ok I guess because they are not much text, but still a bit of a hassle.
I think that your ConnectionString points to the mdf in the Debug/Release folder of your solution, and that file is probably overwritten each time you build your application that's why you think your changes are not persisted. Try setting the ConnectionString to point to the mdf in the project folder (the one that is actually reference by the project).
You can also set the "Copy to output directory" file property to "Copy if newer" rather than "Copy always". If you update the schema of the database in your project then it becomes newer than the database file in the debug directory and it will be overwritten on compile.