LINQ to SQL - method run for 2nd time does not return data changes that happened since 1st time - linq

I have created a method in my data context that is mapped to a SQL stored procedure. The method is used in an ASP.NET application, and it is called twice in the lifecycle of a page. It returns the same single object in both cases (i.e. same primary key).
After the 1st call some data changes are made, so on the 2nd call the stored procedure returns the same record but with different property values. If I use the debugger and SQL Profiler I can verify absolutely that the record being returned has the same PK but different property values between the 1st and 2nd calls.
However, on the 2nd call the object returned by the method is identical to the object returned in the 1st call. It is as if LINQ has run the stored procedure but then totally ignored the results, deciding instead that the data couldn't have changed since the first time it was run, so it may as well return a copy of the original object that it happened to hang on to!
I have experimented with setting the datacontext's ObjectTrackingEnabled to false immediately before calling my method, but this stops me being able to reference related objects.
Here's the code I use to call the method:
Dim stl = _DataContext.GetMyStatus(SelectedUserID)
Dim st As MyStatus= stl.FirstOrDefault
I really need to be able to call this method more than once in the lifecycle of the page, and for it to accurately reflect the current state of the database, so how do I do it?

DataContext produces a single instance per primary key value. It populates this single instance the first time it sees the record, and then returns that instance for any future requests with that key.
If you want to update an existing instance's value from the database, use the Refresh method.
I really need to be able to call this method more than once in the lifecycle of the page, and for it to accurately reflect the current state of the database.
Don't share datacontexts between different page requests.

Related

Spring hibernateTemplete get not getting updated record value

When process is in execution a stored proc is called using Java standard callable statement, which updates the record in db.
Later in flow, using hibernatetemplate get method(passing entity Id object), instance of record is fetched.
The problem is this instance has old value for record columns, before update by stored proc happened.
Its probably happening because hibernateTemplalte was called earlier for same table to update the same record. But even then, if get method is called shouldn't it make a fresh call to db to get updated record.
I tried using flush, but still issue remains.
Any inputs would be appreciated.

From within a Doctrine record class, querying for the same record from the DB overwrites the properties within that class

In one of my Doctrine record classes, I have a preSave method that performs a check. In this check, a query is done on the same table that my record belongs to. This query will fetch one record from the table, and I use the hydrated result to compare to the current record represented by the class.
In some cases, the fetched hydrated result will be the same record as the one I'm working with in the preSave check. However, when this happens, any changes that I've made to the first record are reverted once the query is completed.
Why does this happen? Is there a workaround?
Doctrine might be maintaining a single reference to the record object instance, and not creating a whole new instance in your preSave() method. So when the object is hydrated, any other variables of the same type in your code are 'refreshed'.
To verify this, inspect the object ID's of variables in your code using spl_object_hash() function.
Without seeing your code, workaround suggestions can vary, but one possible workaround is to hydrate an array in preSave():
$query = Doctrine_Query::create()
->select('foo')
->from('Bar b')
->where('b.id = ?', $id);
$results = $query->execute(array(), Doctrine::HYDRATE_ARRAY);
You will lose the ability to use the result as an object, but you will be able to use the contents of the array for comparisons.

Difference between table.update and table.modifiedField

I'm curious what the difference is between overriding a table's modifiedField method versus overriding the update method.
In our case, we are working on switching the field datatype on a table. Since we cannot just change the data type of the field, we make a second field, and copy the information from the first into the second. Eventually, we update all the UI elements (forms and reports namely) to point to the new field, and then remove the old field. To help with copying the information from one field to another, we have been overriding the update method on the table to copy the value from the first field to the second.
I know this would probably be easier to maintain using the modifiedField method, but I'm curious if there are any significant differences (performance, missed updates, etc) by using the update method instead.
The main difference is that the code in modifiedField method is executed without writing into the Database. This way you can change the value of field2, but if a user close the form without saving the record then no updates will be in the DB. While using an update method you certainly write the changes.

LINQ to Entities - How best to obtain the IDENTITY value after calling SaveChanges()

There have been numerous questions posed on this site relating to the retrieval of the IDENTITY after an insert is performed. The way we have been getting the identity is to make the call below, immediately after calling SaveChanges();
context.MyClass.OrderByDescending(c => c.Id).FirstOrDefault();
This seems to work consistently may be completely adequate; however, it has the appearence of opening up a potential for error, should another record be added in between the calls. So the first question is, given that EF performs withing a transacional context, is this method sound?
Secondly, the answer provided to the following question suggests there may be a better way.
Linq to SQL - How to find the the value of the IDENTITY column after InsertOnSubmit()
In that answer, after calling SubmitChanges(), the following call (where "tst" represents the user's class) retrieves the value.
Response.Write("id:" + tst.id.ToString)
This appears to work exactly the same way in LINQ to Entities, where after the call to save changes the instance of the class now includes the id.
context.MyClass.Add(myClass);
context.SaveChanges();
int myNewIdentity = myClass.Id;
Since we are asking for the the actual ID of the class instance (actual record) it would appear to be failsafe. And, it seems logical that the designers of EF should make such basic functionality available. Can anyone confirm that this is proper way to get the identity or at least a best practice?
Yes, LINQ-to-Entities (and LINQ-to-SQL for that matter) will set the generated identity column back in the entity for you after SaveChanges is called. It will also do so for any foreign keys that couldn't be set ahead of time (for instance, a new parent row + a new child row are saved together, and after SaveChanges you'll have the right value in the child row's FK value).
Your particular concern is documented in the 'Working with Entity Keys' page:
http://msdn.microsoft.com/en-us/library/dd283139.aspx
The particular section is 'Entity Keys and Added Objects' and the particular steps are:
4 - If the INSERT operation succeeds, server-generated values are written back to the ObjectStateEntry.
5 - The ObjectStateEntry updates the object with the server-generated value.

Using Linq SubmitChanges without TimeStamp and StoredProcedures the same time

I am using Sql tables without rowversion or timestamp. However, I need to use Linq to update certain values in the table. Since Linq cannot know which values to update, I am using a second DataContext to retrieve the current object from database and use both the database and the actual object as Input for the Attach method like so:
Public Sub SaveCustomer(ByVal cust As Customer)
Using dc As New AppDataContext()
If (cust.Id > 0) Then
Dim tempCust As Customer = Nothing
Using dc2 As New AppDataContext()
tempCust = dc2.Customers.Single(Function(c) c.Id = cust.Id)
End Using
dc.Customers.Attach(cust, tempCust)
Else
dc.Customers.InsertOnSubmit(cust)
End If
dc.SubmitChanges()
End Using
End Sub
While this does work, I have a problem though: I am also using StoredProcedures to update some fields of Customer at certain times. Now imagine the following workflow:
Get customer from database
Set a customer field to a new value
Use a stored procedure to update another customer field
Call SaveCustomer
What happens now, is, that the SaveCustomer method retrieves the current object from the database which does not contain the value set in code, but DOES contain the value set by the stored procedure. When attaching this with the actual object and then submit, it will update the value set in code also in the database and ... tadaaaa... set the other one to NULL, since the actual object does not contain the changed made by the stored procedure.
Was that understandable?
Is there any best practice to solve this problem?
If you make changes behind the back of the ORM, and don't use concurrency checking - then you are going to have problems. You don't show what you did in step "3", but IMO you should update the object model to reflect these changes, perhaps using OUTPUT TSQL paramaters. Or; stick to object-oriented.
Of course, doing anything without concurrency checking is a good way to lose data - so my preferred option is simply "add a rowversion". Otherwise, you could perhaps read the updated object out and merge things... somehow guessing what the right data is...
If you're going to disconnect your object from one context and use another one for the update, you need to either retain the original object, use a row version, or implement some sort of hashing routine in your database and retain the hash as part of your object. Of these, I highly recommend the Rowversion option as well. Using the current value as the original value like you are trying to do is only asking for concurrency problems.

Resources