Entity update failed - entity-framework

Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
I just started learning entity and have done some playing with it in Winforms and now with Webforms. It was working fine for a few days and now I get the error when I try to update a field in the DataView. 'AutoGenerateEditButton="True" in the DV. The DV is wired to the EntityDataSource. A friend accessed the webform and edited one from a diff location and was the last time the edit/update worked.
This is the updating event in case that helps:
Sub dgv_RowUpdating(ByVal sender As Object, ByVal e As GridViewUpdateEventArgs) Handles dgv.RowUpdating
Try
Dim row As GridViewRow = dgv.Rows(dgv.EditIndex)
Dim list As DropDownList = CType(row.FindControl("ddlDoseType"), DropDownList)
e.NewValues("DoseType") = list.SelectedValue
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Any ideas?

You can reproduce this error if you do the following
Client A reads a row with ID = 1
Client B deletes the row with ID = 1
Client A changes the contents of the row
Clinet A tries to save the changes
Since the row with ID = 1 does not exist you get the error that was in your question.
It does not look like the code you posted is causing the error, since that is the updating of the datagrid, not the saving of data to the database.

Related

update One2many Record using Write function called from Onchange (Odoo10)

I am trying to update my One2many record when Onchange method is called. I am fetching the exact value but its not updating the field. Neither I am getting any error.
class abc_1(models.Model):
_name = 'abc.1'
field_a1 = fields.Many2one('crm.team',required=True)
field_a2 = fields.One2many('abc.2', 'field_b1')
#api.onchange('field_a1')
#api.depends('field_a1')
def get_records(self):
for res in self.field_a1.member_ids:
print res.name
self.write({'field_a2':(0,0,'field_b2':res.name})]})
class abc_2(models.Model):
_name = 'abc.2'
field_b1 = fields.Many2one("abc.1")
field_b2 = fields.Char(string='Sales Person')
I am trying to update records fetched but its not doing anything.
First #api.depends trigger onchange event so you don't need
#api.onchange.
Second don't update the database in onchange event because you will commit
changes to the database what if the user click on cancel button the changes
all ready saved in database.
Third if this code works your querying a lot the database, because any call to write will execute update in database. don't query the database inside a loop only if there is no other solution
Four self.write do not work in #api.onchange because the self is not the record is not the real record it's just a dummy record that holds the data passed from
the client side you can check the id you find is always NewID object even if the record is saved in database. usually you find the real record in self._origin (in new API, or list of ids in old API) in
this you can call write and change the values in database a danger thing to do.
#api.depends('field_a1')
def get_records(self):
# when you use depends, best thing you do is to loop so won't get
# singleton error
for rec in self
# create a list to hold the cammands to create the records
res_ids = []
for res in self.field_a1.member_ids:
# now just add the cammand to the list
res_ids.append((0,0,{
'field_b2':res.name,
})
# if you will affect only one element just
# but if more use rec.update() works like rec.write()
# but with onchange it don't save data in database.
rec.field_a2 = res_ids

Deleting/Adding records on a subform that has a similar record source of the main form

I am trying to make a subform that works similarly to a splitform.
I would use splitform but, as far as I could tell, I can't filter only the results of the datasheet portion of the split form, and not the results of the rest.
See here...
The subformPartDetail only returns records where the OrderID is equal to the mainform's OrderID. There is no filter in the mainform so it returns all partDetail Records regardless of the OrderID. In this particular instance, the main form has 21 records to cycle where as the subform only has four.
An issue occured when I use the subform for adding or deleting records. When I try to use the main form to cycle through the records, the added ones were skipped and the deleted ones threw an error telling me that the record I was attempting to go to has been deleted.
I corrected it like this by putting these on the subform events...
Private Sub Form_AfterInsert()
Dim frm As Form
Dim rst As Recordset
Set frm = Forms!PartDetails
Set rst = frm.Recordset
rst.Requery
End Sub
Private Sub Form_Delete(Cancel As Integer)
Dim frm As Form
Dim rst As Recordset
Set frm = Forms!PartDetails
Set rst = frm.Recordset
rst.Requery
End Sub
But say I try to delete the record the mainform is displaying from the subform. That code does not work and will not requery. It throws an error when I cycle away from and then back to that record.
How can I fix this?
I know I can move the record from the deleted one before it deletes by using
rst.move
I don't know where to began for testing whether the record that is being deleted is the same one that the main form is displaying.
Maybe I'm not understanding the situation correctly, but there shouldn't be any need for VBA to achieve this. If the subform is using the Link Master Fields and the Link Child Fields with your subform, those IDs would work automatically. And if you have a relationship set up between the two tables, if you delete the Order record (and have Enforce Referential Integrity: Cascade Delete) selected, it should clear out the line items automatically to avoid orphan records.

Entity Framework and Identity Insert

I am writing an application that exports data and serializes it to file for archiving old data.
There may be occasions where for some reason select data needs to be re-imported. This has been causing me a problem because of an identity column.
To get around this I am performing the work inside a transaction scope. Setting the Identity Insert On for that table and then updating my transaction e.g.
using (TR.TransactionScope scope = new TR.TransactionScope(TR.TransactionScopeOption.RequiresNew))
{
// allow transaction nbr to be inserted instead of auto generated
int i = context.ExecuteStoreCommand("SET IDENTITY_INSERT dbo.Transactions ON");
try
{
// check if it already exists before restoring
var matches = context.Transactions.Where(tr => tr.transaction_nbr == t.transaction_nbr);
if (matches.Count() == 0)
{
Transaction original = t;
context.Transactions.AddObject(original);
context.SaveChanges();
restoreCount++;
But I receive an exception saying:
Explicit value must be specified for identity column in table either when IDENTITY_INSERT >is set to ON or when a replication user is inserting into a NOT FOR REPLICATION identity >column.
I am assuming the entity framework is trying to do some sort of block insert without specifying the columns. Is there anyway to do this in the entity framework.
The object is large and has a number of associated entities that are also deserialized and need inserting so I want to let the entity framework do this if possible as it will save me a lot of extra work.
Any help is appreciated.
Gert Arnold - that was the answer to my question. Thank you.
I did read that elsewhere and had set the value in the object browser so thought this was suffice. I also double checked the value by right clicking the .edmx and Open With to see the details in an XML editor as suggested in another post.
When I checked the value in the XML editor initially it too was "None" so assumed this wasn't my problem. But I guess just going in there and saving rectified the problem first time around.
The second time round after I must have updated the model from the database I had to repeat this step upon your suggestion. But the second time round the StoreGeneratorPattern was different to the one set in the object browser so I needed to manually change it in the XML.
In my circumstance this is fine since normally the records are inserted via another mechanism so the identity is just getting in the way for me as the identity will always be inserted as an old (used to exist) identity value which is being temporarily restored.
Thanks for your help.

Getting correct order of execution of insert, update and delete operations before "SaveChanges"

We have a need to get the entities being added, modified or deleted in the same order as which it is being done on the database.
We are using the below code snippet by overriding the "SaveChanges" method in ObjectContext class to fetch the different entities who have been either added, modified or deleted.
foreach (ObjectStateEntry entry in
ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified | EntityState.Deleted))
{
// Operations on each entity
}
Assume that we have two tables A & B in the database. These are unrelated. We do the below operations on these table using entity framework.
Insert a new row in A
Update a row in B
Insert a new row in B
Update a row in A (not the one inserted in step 1)
Delete a row in B (Not the rows affected in step 2 & 3)
Insert a new row in B
Insert a new row in A
While using the above code snippet, we noticed that the inserts, updates and deletes were grouped together, i.e., we got the entites in order 1,3,6,7,2,4,5.
It is mentioned in this post (http://social.msdn.microsoft.com/forums/en-US/adodotnetentityframework/thread/d8448144-05dd-4c34-b93c-9336c3b62f6e/) that there is no definite way to determine the order of inserts in operations done before a "SaveChanges".
Does the above code snippet fetch the correct order in which these operations are executed on the database.
In case this order is incorrect, is there any other way to get the correct order.
No you cannot change the order of operations. The only way to control the order is to run each operation separately (call SaveChanges after each operation).

atk4.2 form submit-how to get new record id before insert to pass in arguments

I am referencing the 2 step newsletter example at http://agiletoolkit.org/codepad/newsletter. I modified the example into a 4 step process. The following page class is step 1, and it works to insert a new record and get the new record id. The problem is I don't want to insert this record into the database until the final step. I am not sure how to retrieve this id without using the save() function. Any ideas would be helpful.
class page_Ssp_Step1 extends Page {
function init(){
parent::init();
$p=$this;
$m=$p->add(Model_Publishers);
$form=$p->add('Form');
$form->setModel($m);
$form->addSubmit();
if($form->isSubmitted()){
$m->save();//inserts new record into db.
$new_id=$m->get('id');//gets id of new record
$this->api->memorize('new_id',$new_id);//carries id across pages
$this->js()->atk4_load($this->api->url('./Step2'))->execute();
}
}
}
There are several ways you could do this, either using atk4 functionality, mysql transactions or as a part of the design of your application.
1) Manage the id column yourself
I assume you are using an auto increment column in MySQL so one option would be to not make this auto increment but use a sequence and select the next value and save this in your memorize statement and add it in the model as a defaultValue using ->defaultValue($this->api->recall('new_id')
2) Turn off autocommit and create a transaction around the inserts
I'm from an oracle background rather than MySQL but MySQL also allows you to wrap several statements in a transaction which either saves everything or rollsback so this would also be an option if you can create a transaction, then you might still be able to save but only a complete transaction populating several tables would be committed if all steps complete.
In atk 4.1, the DBlite/mysql.php class contains some functions for transaction support but the documentation on agiletoolkit.org is incomplete and it's unclear how you change the dbConnect being used as currently you connect to a database in lib/Frontend.php using $this->dbConnect() but there is no option to pass a parameter.
It looks like you may be able to do the needed transaction commands using this at the start of the first page
$this->api->db->query('SET AUTOCOMMIT=0');
$this->api->db->query('START TRANSACTION');
then do inserts in various pages as needed. Note that everything done will be contained in a transaccion so if the user doesnt complete the process, nothing will be saved.
On the last insert,
$this->api->db->query('COMMIT');
Then if you want to, turn back on autocommit so each SQL statement is committed
$this->api->db->query('SET AUTOCOMMIT=1');
I havent tried this but hopefully that helps.
3) use beforeInsert or afterInsert
You can also look at overriding the beforeInsert function on your model which has an array of the data but I think if your id is an auto increment column, it won't have a value until the afterInsert function which has a parameter of the Id inserted.
4) use a status to indicate complete record
Finally you could use a status column on your record to indicate it is only at the first stage and this only gets updated to a complete status when the final stage is completed. Then you can have a housekeeping job that runs at intervals to remove records that didn't complete all stages. Any grid or crud where you display these records would be limited with AddCondition('status','C') in the model or added in the page so that incomplete ones never get shown.
5) Manage the transaction as non sql
As suggested by Romans, you could store the result of the form processing in session variables instead of directly into the database and then use a SQL to insert it once the last step is completed.