i have problem with visual studio or entity framework.
Situation is simple:
I have Employes, and i have data grid view for present, when i click on Edit employe, i get ID from employe
int employeID= Convert.ToInt32(dgvEmployes.SelectedRows[0].Cells[0].Value);
frmEditEmploye edit = new frmEditEmploye ();
edit.employ = new ePoliticsServis.Data.Employ();
edit.employ= eServis.Data.EmployesService.SelectEmployeById(employeID);
and i get Employe from db, and i load employe in new form for editing,and i save updated date, and go in database refresh table and all is good, all is updated, butproblem is, when i back on preview, datagrid view (datagrid is refreshed with new data, binding, all is ok) and again click on same employe for editing, i have form for editing but with old data, no with new upadated data from database for the same employe, when i shotdown my application and run again then i get new data refreeshed and updated. i really dont know where is problem..
I suspect the problem is your data context is retrieving the data from memory and not the database see a previous answer of mine for a possible solution.
Remember to surround your data context in a Using statement to correctly dispose of it.
From your latest comment I can see you are probably not disposing of your context correctly, I think this is called 'connection' in your code. This is probably a member variable of the class,
You'll probably need to change the method to something like this:
//You need to check the type Connection is and use it here. I'm using 'Connection' because I don't know the name of your context.
Using (var myContext = new Connection())
{
var returnValue = myContext.dm.epsp_Employ_SelectById(id).FirstOrDefault();
}
return returnValue;
One more thing...Check the database is being updated after you save the record. If it isn't you need to call SaveChanges().
Related
I have a Winforms test application that I'm using to try to learn about Entity Framework Core.
I have a datagridview bound to my table and I can edit fields and call context.SaveChanges() - works fine.
What if I have edited several cells on different rows, deleted and added a row, then changed my mind and I don't want to save? How can I discard the changes and refresh the datagridview with the original data?
I call EntityFrameworkQueryableExtensions.Load(context.entity) and then dataGridView1.Refresh() but my form remains unchanged with my changes.
dataGridView1.DataSource = context.enity.Local.ToBindingList();
To load data from database you have to instantiate the Context again:
context = new SampleDbContext(options);
then you can reload your grid any way that's possible. I think the easiest possible way is to assign it again:
dataGridView.DataSource = context.MyDbSet;
And one more thing (just in case you want to learn more); EF is not designed to be used with long lived contexts. The best way to use EF is to dispose the DbContext instance after you are done with it:
using(var ctx = new SampleDbContext()){
instances = ctx.MyDbSet....
}
I just added a new field to a table I have ("Leads")
Saving and retrieving work fine for all fields except my new field that I added directly to the DB. I'm doing the same thing for the new field as the other fields
objLead = new Leads();
objLead.PhoneNumber = txtPhoneNumber.Text; //this one works
objLead.MobilePhone = txtMobilePhone.Text; //this one doesn't
Leads ins = LeadsManager.Save(objLead);
my save function is..
public static Leads Save(Leads objLead) {
if (objLead.LeadId == 0) {
//objLead.InsertBy = Convert.ToInt32(HttpContext.Current.User.Identity.Name);
objLead.InsertDate = DateTime.Now;
objLead.InsertMachineInfo = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"].ToString();
DbContextHelper.DbContext.Add(objLead);
}
//secUser.UpdatedBy = Convert.ToInt32(HttpContext.Current.User.Identity.Name);
objLead.UpdateMachineInfo = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"].ToString();
objLead.UpdateDate = DateTime.Now;
DbContextHelper.DbContext.SaveChanges();
return objLead;
}
I'm fairly new to EF so I'm not sure if I'm missing something.. I went to the Leads class and added the new property so intellisense recoginzies when I put objLead.mobilePhone.. I'm just not sure why it's not saving to the DB.. Thanks for the help!
After adding your column to your physical DB table perform the following steps:
Go into your model (.edmx)
Right click design area
Update Model from database...
Click the refresh tab on the dialog that appears
Finish
This should update your poco classes that were autogenerated previously with the new column that was added. This should fix your issue if you're experiencing what I think you're experiencing.
Note that regenerating your POCOs in this manner will remove any changes that you did to them manually (if any).
EDIT:
I'm not sure if this actually works or not, but you could try it. If you go directly into the POCO class created and add your new property with the correct data type, that might work.
Find your POCO classes by expanding your .edmx file from the solution explorer, then [modelName].tt, then select your [tableName].cs.
If you added a string to the table you could add:
public string NewColumnName { get; set; }
again I don't know if going this route actually works, refreshing your model based on the database is your best bet.
I had been getting very strange behavior form entity framework. I am coding a WebApi application so the objects I get from the browser are disconnected/detached. The data I get back is transactional such that it does not match any given table in the database. I have to do a number of lookups and data manipulation to get the actual updates to be done on the database.
The problem I seem to have is that in querying the data I am filling up the Tracked Changes cache. That wouldn't seem to be a problem to me since the true source of data should be the database. When I finally make the data changes and I call SaveChanges I get constraint errors. Here are my steps.
Query data.
Create rows to be inserted.
compare rows to db and make db changes.
After reviewing the data in Ctx.ChangeTracker.Entries() I found that an entry to be deleted was marked as Modified when it was supposed to be deleted. The way I worked around it was by Creating a new context for step 3. And it magically started working. I thought that was it, but in my test case I do a last read from the database to verify that my transaction was writing correctly. And I was getting an extra row that should already be deleted. And in fact was, when checking the db directly. Again a new context to do that last read fixed the problem.
I just assumed the default cache setting would just be used to track changes and not to speed up queries.
If I try to use AsNoTracking in my queries I also get into trouble because if I try to delete a row queried like that I get an error. And in my code I don't know if I am going to delete or modify until later on. Is there a way to clear the cache so I don't need to create a new context?
Is there a better way to deal with these issues?
EDIT:
AsNoTracking will do the trick, to some extent. I still found myself instantiating more copies of DbContext in order to prevent errors. Many to one entities have to be deleted in order or null foreign key errors are triggered.
var details = oldInvoice.details.ToList();
Context.Entry(oldInvoice).State = EntityState.Unchanged;
Context.Entry(oldInvoice).State = EntityState.Deleted;
details.ForEach(a => Context.Entry(a).State = EntityState.Deleted);
Entity Framework offers an exception DbUpdateConcurrencyException that you can catch on your calls to SaveChanges(). you could loop through the errors something like this:
catch (DbUpdateConcurrencyException ex)
{
saveFailed = true;
// Get the current entity values and the values in the database
var entry = ex.Entries.Single();
var currentValues = entry.CurrentValues;
var databaseValues = entry.GetDatabaseValues();
// Choose an initial set of resolved values. In this case we
// make the default be the values currently in the database.
var resolvedValues = databaseValues.Clone();
// Have the user choose what the resolved values should be
HaveUserResolveConcurrency(currentValues, databaseValues,
resolvedValues);
// Update the original values with the database values and
// the current values with whatever the user choose.
entry.OriginalValues.SetValues(databaseValues);
entry.CurrentValues.SetValues(resolvedValues);
}
} while (saveFailed);
also, your update code sounds suspicious as well. Usually when you pass data out to a client through WebApi or other mechanisms, the data that is returned doesn't have the tracking data, so you should be checking to see if it exists and re-attaching it to the context and changing it's state to EntityState.Modified if so before calling SaveChanges().
I have a C# mvc3 application that is using entity framework to pull data from my SQL server database. I discovered that it seemed to be pulling "old" or "cached" data instead of the data that was currently in the DB.
Once I updated the model it seemed to pull the new data.
My question is how do I make sure that I am always pulling "live" data from the database and not getting "cached" or "old" data?
When I ran the following code and checked the value of tblcompanyinfo.companyname it was returning an old company name (different from what was currently in the DB).
Once I updated the model and re-ran it, it returned the current value of company name.
private static ApptReminderEntities db = new ApptReminderEntities();
tblCompanyInfo tblcompanyinfo = db.tblCompanyInfoes.SingleOrDefault(t => (t.CompanyID == lCompanyID));
Thanks!
This may be due to your shared and static DbContext Instance i.e.
private static ApptReminderEntities db = new ApptReminderEntities();
Replace it with using block as below:
using(ApptReminderEntities db = new ApptReminderEntities())
{
tblCompanyInfo tblcompanyinfo = db.tblCompanyInfoes
.SingleOrDefault(t => (t.CompanyID == lCompanyID));
}
Using using statement, you are
Creating new ApptReminderEntities instance each time.
Doing whatever you want in database.
Using is automatically closing and disposing your instance.
So, for each trip to database, use using so that you will create new instance of your context each time.
The problem is that you're not creating a new context for each query - you've defined it as static.
You should always create a new ApptReminderEntities for each operation you do on the database.
You can use a repository pattern or similar. In my case, every operation I would do
var employees = new EmployeeRepository().GetEmployees();
and in the Employee repository constructor, it creates a new EmployeeEntities()
This makes it quite easy to unit test too, as I can overload my repository and pass in a dummy context.
I am having an issue with the SubmitChanges function provided by the linq to DB implementation in C#. When I run the command, nothing throws an error but the record never gets updated. I have looked up the issue almost everyone says that it is in issue with the table nothing a primary key. However my table has a primary key assigned to it and yet SubmitChanges does not happen. To give you an overview of what I am executing, I here is a sample:
public void setApproval(string approvalCode, int ID)
{
using (DatabaseDataContext context = new DatabaseDataContext(DBConnection().getConnectionString()))
{
myRecord con = getRecord(ID); //Gets the record succesfully, PK field in tact
con.ApprovalStatus = approvalCode;
context.SubmitChanges();
}
}
As commented above, the record is successfully obtained with all the data in tact, including the PK field used to identify it. The database connection user is given the rights to update the table, though here I would expect it to break and complain.
Any ideas? Please let me know if I have not provided enough information. Any help is greatly appreciated!
You should get the object through context
public void setApproval(string approvalCode, int ID)
{
using (DatabaseDataContext context = new DatabaseDataContext(DBConnection().getConnectionString()))
{
myRecord con = context.TableName.First(item => item.ID == ID); //Gets the record succesfully, PK field in tact
con.ApprovalStatus = approvalCode;
context.SubmitChanges();
}
}
When you get the object via Context, it keep track of changes you make and then it save those changes on SubmitChanges
Where does getRecord(ID) get its context to return a record? It is not getting passed to the method, so I assume it is using a different context. SubmitChanges() would only see changes for the current context, not the context that getRecord(ID) used.
Are you checking to see if the data was updated with code or with an independent DB tool?
If in code, your read code is as suspect as the write code:
I was having similar issues when two applications with no common API were communicating through a database. The context is not a reflection of what is in the DB right now, and no amount of telling it to refresh is going to entirely fix the problem. If you need to inspect the database for something entered by another program or thread, you have to create a new database context object to inspect the database. The old database context object may still have the old data from before your most recent update.
Your getRecord function needs to create a new context or take the current context that you just edited as a parameter. If it uses a static or class level context it will not have the latest data.