I am using Visual Studio 2012. I have a very simple Products table in a Local Database (cleverly named Database1). It has two fields: id and Name. I preloaded it with a few test data.
The following code should update the Name of the first Product. Internally, it does. I can retrieve all Products and see that the first one's Name is "Shirt." But the change is never flushed to the database. The record is never updated. Examining the database reveals that the name has not been changed.
My question is simple: Why are changes not being sent to the database?
using (var context = new Database1Entities())
{
var products = context.Products;
products.First().Name = "Shirt";
context.SaveChanges();
}
Thanks in advance.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
EDIT:
I tried my best to enter the full code and output here. But, no matter what I do, I continue to get the "Your post appears to contain code that is not properly formatted" error message. After 30 minutes I am giving up.
EDIT:
The code and output is here: http://pastebin.com/GmQtwAND
I discovered the issue...and its solution.
The "Copy to Output Directory" property of the database file was set to "Copy always." This, of course, meant that every time the application was built, a fresh copy was placed into the Bin directory. The fix was to set it to "Copy if newer." Doh.
In other words, the changes were being persisted in the database, but then the database was being clobbered when the application got rebuilt.
Well this could mean that you're not tracking changes, how about you try to set the State to -> Modified and see if it's going to work:
var product = products.First();
product.Name = "Shirt";
product.State = EntityState.Modified;
context.SaveChanges();
If you want to enable it for the context you can do it like this:
context.Configuration.AutoDetectChangesEnabled = true;
Related
I have a database with three tables in it. I created all the tables within Visual Studio. My C# code is connecting to the database using Linq to SQL. The table I am having problems with is not updating on SubmitChanges().
using (DataClasses1DataContext db = new DataClasses1DataContext())
{
tbl_Inventoryv2 inv = new tbl_Inventoryv2();
inv.Title = addTitleTextBox.Text;
inv.Model = addModelTextBox.Text;
inv.Category = addCategoryTextBox.Text;
inv.Quantity = int.Parse(addQuantityTextBox.Text);
inv.Price = decimal.Parse(addPriceTextBox.Text);
inv.Description = addDescriptionTextBox.Text;
db.tbl_Inventoryv2s.InsertOnSubmit(inv);
db.SubmitChanges();
int id = inv.IdInventory;
MessageBox.Show($"Item creation successful. Item number is {id}");
}
My database does have a primary key called IdInventory that is set to increment. Within the program, the correct increments are working as shown in my MessageBox statement above, but it never actually gets saved to the database. I have also checked the properties of the database file in Visual Studio and the path to the database is correct, as well as the Copy to Output Directory is set to Copy if Newer. Most of the questions I have looked up indicate that is usually the problem, but that doesn't look like the case for me. I am new to SQL and interacting with it via Visual Studio/c#, and SQL in general, so any input is greatly appreciated.
I have seen the other posts on this subject. Yet so far there has been no solution. I am working with Visual Studio 2013 in C#.
I have a database "Database1.mdf" with one table called Customers, which just has two records. I created the DataSet named CustomersDataSet (Menu: Project, Add New Data Source...) based upon this database.
This is my code.
CustomersDataSetTableAdapters.CustomersTableAdapter cta = new CustomersDataSetTableAdapters.CustomersTableAdapter();
CustomersDataSet ds = new CustomersDataSet();
// Fill our customersDataSetTable with the data from customers adapter
cta.Fill(ds.Customers);
Console.WriteLine("BEFORE");
foreach (CustomersDataSet.CustomersRow customer in ds.Customers.Rows)
{
Console.WriteLine(customer.FirstName + " " + customer.LastName);
}
Console.WriteLine("\nMaking changes now...");
// Insert a new record
CustomersDataSet.CustomersRow newCustomer = ds.Customers.NewCustomersRow();
newCustomer.FirstName = "Brian";
newCustomer.LastName = "Faley";
newCustomer.City = "Denver";
newCustomer.State = "CO";
ds.Customers.AddCustomersRow(newCustomer);
// Update a record, [0] = gets access to the first row of the customers table
ds.Customers[0].FirstName = "Robert";
// Delete a record
ds.Customers[1].Delete();
// Update the dataset ds. Commit changes to the database
cta.Update(ds);
Console.WriteLine("\nAFTER");
foreach (CustomersDataSet.CustomersRow customer in ds.Customers.Rows)
{
Console.WriteLine(customer.FirstName + " " + customer.LastName);
}
It works insofar as I do see the changes made to the dataset after "AFTER".
Yet I can run it as often as I wish - never are the changes written to the underlying database. The Update should do just that, but it does not. There is no AcceptChanges() in my code. I have followed up on all these suggestions - they do not lead anywhere.
Would someone have an idea?
I googled far and wide and all posts on this issue are unsolved.
When you debug the application the mdf file is copied to the bin\debug folder and your changes are committed to the database there.
Every time you start the project the mdf in the debug folder gets overwritten with the original database.
You can stop this behavior by going to the database settings in your solution and set the database to copy only if your version is newer.
Chances are your code was working all along.
Hope this helps.
So I have a Database that I created a Dataset from, I'm attempting to run an Update on it and I cannot get it to update the Dataset (and subsequently the Database) with the result. I built the Query using Visual Studio's query builder and when I run it through there it changes the data in the way that it should. When I run the code I put in a MessageBox to show the number of rows the query changed and it is returning 1 as it should. I'm at a loss as to why it won't 'commit' the update and I'm sure I'm missing something very simple.
Here is the Query I setup (named "UpdateQuery")
UPDATE Bug_Master
SET Name = #Name, Test_App = #Test_App, Bug_Type = #Bug_Type, Bug_Active = #Bug_Active, Bug_Description = #Bug_Description, Bug_Keywords = #Bug_Keywords
WHERE (Id = #Original_Id);
In the Load event for the form I have
this.bug_MasterTableAdapter.Fill(this.bugManagerDataSet.Bug_Master);
And here is where I am calling the Query and trying to update (I know I should use 'using' but I'll pretty up the code after I get this to work so forgive the inelegance)
SqlConnection connection = new SqlConnection(strSQLConnectionString);
connection.Open();
int iResult = bug_MasterTableAdapter.UpdateQuery("Error One 1", "PassVault", "Runtime", "True", "Description Test", "Keywords Test", 1);
MessageBox.Show(iResult.ToString());
bug_MasterTableAdapter.Update(bugManagerDataSet.Bug_Master);
connection.Close();
As I mentioned above the MessageBox shows '1'. Is there a critical step I'm missing on how to do this? It has been a long time since I messed with SQL so I've had to bumble my way back to it and have no doubt I've missed/messed up some things.
Thanks in advance.
erik
Found the solution. Turns out the 'copy to output directory' property on the database file was set to 'always copy'. So when I ran the program it would make changes to the database in the \bin\debug folder while I was looking at the one in the app folder. Then when I would restart the program to check the values in there it would overwrite the changed version of the database in \bin\debug with the unchanged version from the project.
So, the upshot is for anyone else that runs into something similar is set the 'Copy to Output Directory' option on the database to 'Copy if Newer'.
Thanks to all who took a look.
erik
Hi I had developed a C# Budget application using SQL Compact and EF4, I created the EF model through the VS2010 Entity Data Model template. It is all working very well. However I am considering developing a iPhone app to support cash transactions and thought it would be better to have the back end DB supported on both platforms. After creating the SQLite DB and creating a new model I have come across a problem when trying to access referenced data via the Navigation properties in my model. I am getting a NullReferenceException when trying to display a property of a referenced table.
When using the following code I get the exception on the last line:
BudgetEntities budget = new BudgetEntities();
var accounts = budget.BankAccounts.ToList();
foreach (BankAccount a in accounts)
{
Console.WriteLine("Name:" + a.Description);
Console.WriteLine("Number:" + a.AccountNumber);
Console.WriteLine("Type:" + a.BankAccountType.AccountType); //Exception occurs here.
}
Strange thing is that the exception doesn't occur in this example. I'm not sure what is going on?
BudgetEntities budget = new BudgetEntities();
var accoutTypes = budget.BankAccountTypes;
var account = new BankAccount();
account.ID = Guid.NewGuid();
account.AccountTypeID = accoutTypes.First(t => t.AccountType.StartsWith("Credit")).ID;
account.BSB = "3434";
account.AccountNumber = "32323";
account.Description = "Test";
account.TrackingAccount = true;
budget.AddObject("BankAccounts", account);
budget.SaveChanges();
var accounts = budget.BankAccounts.ToList();
foreach (BankAccount a in accounts)
{
Console.WriteLine("Name:" + a.Description);
Console.WriteLine("Number:" + a.AccountNumber);
Console.WriteLine("Type:" + a.BankAccountType.AccountType); //Exception doesn't happen.
}
This is only a simple example and I know I could fix it by adding .Include("BankAccountTypes") to the query however I have other queries that are quite complex that are creating object which include properties from referenced object with in the query and I am not quite sure how to get around this issue for them.
EDIT:
After having a break between projects I have come back to this problem and I have finally resolved my problem. it had nothing to do with the code. It was with the data. I had converted a SQL Compact database to SQLite via a dump and load and had the syntax wrong for my Guid column data. I was inserting the Guid as '7cee3e1c-7a2b-462d-8c3d-82dd6ae62fb4' when it should have been x'7cee3e1c7a2b462d8c3d82dd6ae62fb4'
Hopefully the hair I pulled out working through this problem will grow back :)
Thanks everyone for your input.
In second example your code snippet begins with:
var accoutTypes = budget.BankAccountTypes;
This loads all bank account types to your application and you don't need lazy loading anymore (EF will automatically recognize that these entities were already loaded and fix relations with bank accounts).
First check if your account class is dynamic proxy (just check type of a in the debugger). If it is not you made some mistake in the class definition and lazy loading will not work. Next check if lazy loading is enabled on your context instance (budget.ContextOptions.LazyLoadingEnabled property).
Make sure the BankAccountType property is declared virtual in BudgetEntities.
I can successfully create an iteration path via:
var commonservice = collection.GetService<ICommonStructureService>();
// create new area path and iteration path
var iterationRoot = commonservice.GetNodeFromPath("\\MyTeamProject\\Iteration");
var newIterationPath = commonservice.CreateNode("my new sprint", iterationRoot.Uri);
However, when I try and assign this path to a work item and save it the field doesn't validate.
If I run the tests again (with the iteration already created) the same code succeeds.
Does anybody know how to make this work?
This fixed it for me:
WorkItemStore wis = (WorkItemStore)tfsTeamProjColl.GetService(typeof(WorkItemStore));
wis.RefreshCache();
wis.SyncToCache();
Maybe it will help someone.
I experienced exactly the same behavior, and unfortunately #JWC answer didn't help. The solution which works for me can be found by this link.
So, this is a quick summary in case the original answer gets lost.
The key point is to use WorkItemServer class. It lives in the Microsoft.TeamFoundation.WorkItemTracking.Proxy.dll assembly.
First of all, you create a WorkItemStore instance:
var store = collection.GetService<WorkItemStore>();
Then, create necessary iteration paths:
var commonservice = collection.GetService<ICommonStructureService>();
var iterationRoot = commonservice.GetNodeFromPath("\\MyTeamProject\\Iteration");
var newIterationPath = commonservice.CreateNode("my sprint", iterationRoot.Uri);
Next, refresh the cache in TFS (I suspect this is similar to pressing F5 in web interface):
var wiServer = collection.GetService<WorkItemServer>();
wiServer.SyncExternalStructures(WorkItemServer.NewRequestId(), commonservice.GetProjectFromName("MyTeamProject").Uri);
store.RefreshCache();
And finally, assign newly created work item to the newly created iteration:
var wi = new WorkItem(store.Projects["MyTeamProject"].WorkItemTypes["Product Backlog Item"]);
wi.Title = "Hello from API";
wi.Description = "This work item was created from API";
wi.Fields["Assigned To"].Value = "Yan Sklyarenko";
wi.IterationPath = FormatPath(commonservice.GetNode(newIterationPath).Path, "Iteration", "MyTeamProject");
wi.Save();
That's it! The method FormatPath translates the iteration path to the form required by the work item IterationPath field, that is from \MyTeamProject\Iteration\my sprint to MyTeamProject\my sprint.
Hope this can save some time.
NOTE: I run this towards TFS 2013.
You are likely running into a caching issue. Try clearing the cache after you create the iteration. A couple things you could try:
Get a new copy of the WorkItemStore.
Disconnect and reconnect to TFS
Check to see if there's a "refresh" method on either the WIS or on the TFS server objects. I've shut down my dev instance of TFS for the night, and I don't recall if there's anything like it.
If that's not quite it, post your code and I'll see if I can reproduce it.
I had the similar issue. I created Areapath and then created a query where the AreaPath was used. I did call store.RefreshCashe() but it did not work. Only in Debugger when I run store.RefreshCashe() two times manually.
Thanks "Yan Sklyarenko". I tried your Suggestion and it works fine (TFS Server 2012).