Devart InsertAllOnSubmit doesn't update db generated fields - linq

I'm using Devart's Linq to Oracle components. I've got a table with a field that's updated via a sequence in the database. This works fine when inserting one row:
Dim db As New DataContext
db.MyObjects.InsertOnSubmit(MyObject)
db.SubmitChanges()
At this point, MyObject.Version will contain the version identifier that was generated in the database. So I was expecting that this code would work fine:
Dim db As New DataContext
db.MyObjects.InsertAllOnSubmit(MyObjectsList)
db.SubmitChanges()
But when I do this, the Version field is unchanged in all of the objects in MyObjectsList, even though the rows are being added to the table.
What am I missing here? Thanks in advance.

For the database-generated value of an entity member to be retrieved when this entity is inserted, one of the following should be true:
the 'Auto Generated Value' property of this member is set to true;
the 'Auto-Sync' property of this member is set to 'OnInsert' or
'Always'.
Please check that either of these conditions is satisfied. Also, please try updating to the 6.30.160 version of dotConnect for Oracle (if you are using a prior build).
If the problem persists, could you please send us a test project with which it can be reproduced?

Well, I found the problem and it had nothing to do with devart. The problem turned out to be that I was passing an IEnumerable(Of MyObject) to the method, which was the result of another query. When I materialized this list to a List(Of MyObject) and passed that instead, the db generated fields did appear in my objects. I must admit I don't quite understand why this mattered, but at any rate it fixed the problem. Hope this helps someone else some time

Related

Entity Framework returns different result with AsNoTracking

I use Entity Framework in combination with an Oracle database. If I create a query like
myLinqStatement.ToListAsync()
I get wrong data returned as a result. If I change the statement to
myLinqStatement.AsNoTracking.ToListAsync()
I get the correct data.
I also checked the native SQL query, which is generated by myLinqStatement.ToListAsync(). The generated SQL query is correct, because I get the correct data.
So is there a problem in the mapping? And why is it working with AsNoTracking?
Thanks!
What AsNoTracking does is to retrieve the data without attaching it to the context, hence any changes you apply over the data do not take effect unless you attach it again so that EF knows it should track its changes.
The code snippets you've provided do not show the whole picture, from the moment a context is created, but is it possible that other parts of your code mutate data before you call myLinqStatement.ToListAsync()?
As you mention that myLinqStatement.AsNoTracking.ToListAsync() returns expected data, makes me assume that there are some side effects in your code that AsNoTracking simply is not aware so just returns whatever it finds in your db
I came across this question because I had a similar issue with Entity Framework Core querying a DB view, the issue was cause because view didn't have a key defined, after defining a key for the entity that map to that DB view, the query returned the same result in both cases (using AsNoTracking or without using it).
In T-SQL a key for a DB view can be defined this way:
CREATE UNIQUE CLUSTERED INDEX UQ_MyDBViewName_ColumnKey
ON dbo.MyDBViewName (ColumnKey);
And in code, you can map the key using the [Key] attribute in the corresponding property of the entity or using the EF fluent API. It will depend of what the project is using.
Either way, using AsNoTracking on a query that goes directly to a DB view makes a lot of sense. Also, if for some reason the query of the view does not allow us to define a key for that view, then the option is to use AsNoTracking.
Hope it helps anyone else having the same issue.

LINQ update statement using generic table and column names

OK, I've seen a lot of posts on creating generic LINQ statements, but these are usually based on select queries. What I need is a LINQ UPDATE statement that takes a generic parameter for the table to update and a generic parameter for the column to update.
The data model I'm working with has dozens of tables, and each table has potentially dozens of columns. What I'm really driving toward is a single Update statement that allows me to tell it at runtime which table and which column to update.
Dealing with data typing of these dynamically supplied fields will also be an issue since obviously I can't update a DateTime column with a decimal value for example.
So, can anyone point me at some code that shows a LINQ update process using generic parameters for table and column names.
Any help would be greatly appreciated!
You didn't specify Entity Framework with DbContext but if that is what you are using, this is pretty easy. The following code is written to work within the NerdDinner sample which can be downloaded from http://nerddinner.codeplex.com/
This code locates a dinner based on the id and sets the address property to "New Value"
Dinner dinner = db.Set<Dinner>().Find(id);
var entry = db.Entry(dinner);
entry.Property("Address").CurrentValue = "New Value";
db.SaveChanges();

The data reader is incompatible with the specified... A member of the type, 'Finalised', does not have a corresponding column in the data reader

I have added a column in my Sql Server Db then in VS i updated model from database, there a template auto generated some code.
The code compiled fine, but when i try access a the data base, the following error occurs:
The data reader is incompatible with the specified
'CompassModel.tbSalesContract'. A member of the type, 'Finalised',
does not have a corresponding column in the data reader with the same
name.
Finalised is the new column i added to my database.
Does anyone know how to track this down, and if so, is there a fix or methodology to follow to avoid in the future?
If you are using a SP then update the newly added column in that Or If you are using inline query put the exact name of the newly added column . The template you are talking about does not contain the newly added column name ..Try to edit the template ..the issue will be resolved.
If you are using a SP, then please make sure the alias names used.. ie. for eg: It should be written as
fieldname as 'aliasname'
thanks,
criss thomas
Hopefully this helps someone out but when I received this error I was trying to return an entity type from a stored procedure.
To fix this I had to add the correct function import mapping. In your edmx go to the Model Browser view and navigate to Funtion Imports. Right click your sproc name and select function import mapping. There you can map your sproc return results to the appropriate entity property.

Changed existing entity model and manually updated SQL Server database but still get context changed error

I have an existing MVC3 application and database that is on a SQL Server 2008 R2 and I had to add a bool item to an existing model.
After I added it to the model, I rebuilt and published the project. Then I opened up SQL Server Management Studio and went to the table and added the entry to the column as a bit, I had to make it nullable since the table already contains data.
I thought this would be all that I would need to do to get everything working. However I got this error:
The model backing the 'psllc_DB' context has changed since the database was created. Either manually delete/update the database, or call Database.SetInitializer with an IDatabaseInitializer instance. For example, the DropCreateDatabaseIfModelChanges strategy will automatically delete and recreate the database, and optionally seed it with new data.
I'm not sure what else to do, I went back to the code and changed the bool to bool? so it will be nullable but this didn't help either. I can't drop the entire database since it's full of data, however as a last ditch possibility I could drop this table and re-create it cause it only has a few entries, but I don't know if that will work. I'm not sure what else to do so any advice would be very appreciated.
Update
Since I'm not getting any responses, let me rephrase my question.
How should I update my database (a SQL Express mdf file) to add a bool Column to a Table that has data already? I need the database to match my updated MVC 3 Entity Code First model otherwise I get the above error.
Thanks
Since this is code-first, you should do this code-first: change the class and use EF-migrations to change the database. The way you do it, the model and the database may match, but the meta information in the database is not updated.
By the way, if you supply a default value, you can add a non-nullable column.

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