problems with timestamp and concurrency - c#

I am using EF 4.0 and I have in my database a table with a timestamp field because I want to control the concurrency in this table.
Then, I created my edmx and I generated the POCO classes with the template DBContext.
The first try that I do is, in the edmx, in the timestamp field, I set stored generated pattern to none. Then in my code I do:
myContext.MyTable.Attach(myEntity);
myContext.Entry<MyTable>(myEntity).Property(p => p.AnyFieldNoTimestamp).IsModified = true;
myContext.SaveChanges();
This give me an exception that says that is not possible to update a timestamp column.
If I have I only marked a field to modified, and this field is not the timestamp, why I get this error?
Then I try to set the propery stored generated pattern in the edmx to Indentity.
really I have a transaction and two saveChanges. In this second try, the first savechanges does not give any error but in the second savechanges I get the excepcion 0 rows affected, because it seem that the timestamp of the entity has changed from the first savechanges to the second, so in the concurrency control I get this excepction.
So I would like to know how can I use a timestamp field inside a transaction and two save chages.
Thanks.

I try to use the set Computed and in this case works correctly.

Related

Handle Optimistic Concurrency in SQL Server with EF Core - when updating child, how to update the parent?

I have two entities one of them paper and the other one is paper line.
I am using SQL Server to store the entity records, each entity is represented by a table in the database
PaperEntity contains columns
Id, Color, TimeStamp (RowVersion), etc...
PaperLineEntity contains columns
Id, PaperId(FK), lineContent, TimeStamp (RowVersion), etc...
I am thinking about how can I prevent two users to update two different lines in the same paper, my idea is when you update the line you have to update the timestamp for the paper record that this line belongs to it, any ideas on how can I manage that in EF Core?
When fetch lines of Paper, get TimeStamp(RowVersion) too,
When user save the line,
first compare timestamp
if it is different, so you return an error else it is same, then you Allow update it
You can use concurrency tokens. Idea is the same as you described: you have a special property which is updated together with each update of entity. You should mark this property using special attribute or using fluent configuration. EF Core will compare old_value (initially read from db) and current_value (currently presented in database) automatically during each update. If they are not equal special exception will be thrown.

How to avoid insert a property class into SQL database in C#

I'm having troubles when I do a POST endpoint.
When I run the code to insert data into my database, it breaks because of an invalid column name; I'm inserting the class entity that has an extra property (that is always null, except when I'm bringing it from another table with an inner join). This property is read as a column from the entity that I'm trying to insert and it breaks.
There is a way to ignore this property? I'm not using Entity Framework, I've tried a few ways already. That is why I'm asking.
EDIT: I'm having these error for INSERTS and UPDATES because I'm saving the entity that has 1 extra property that doesn't match with the table. My question is, there is any way to ignore it for these cases?
await _clientRepository.UpdateAsync(client);-> this line breaks because client.Description doesn't exists in the sql table.
[NotMapped] -> didn't work.

DatabaseGeneratedOption: Identity vs. Computed

I am trying to understand the (functional) difference between the two DatabaseGeneratedOption's in Entity Framework (code first):
DatabaseGeneratedOption.Identity
DatebaseGeneratedOption.Computed
I have read the documentation, but I do not understand the functional difference between the two.
The option Identity is described as The database generates a value when a row is inserted. But I cannot update the value later if I try I get an exception saying that I cannot modify a column with Identity pattern.
The option Computed is described as The database generates a value when a row is inserted or updated. However, this is just what you tell Entity Framework, so far I have not been able to achieve this, without SQL triggers. If I try to update the value, nothing happens (Entity Framework refuses to overwrite the existing value).
So what I am left with, is two functionally identical options. I can have a default value in my SQL table, which will be applied on the insert. And I cannot update this value afterward (using Entity Framework). So where in lies the difference in how they should be used?
A computed column contains a value that is computed (hence the name) when the record is requested.
A computed column can be composed of other column values, constants and function return values.
You could for example create a computed column for an invoice expiry date:
CREATE TABLE Invoice
(
InvoiceDate DATETIME NOT NULL,
ExpiryDate AS DATEADD(DAY, 30, InvoiceDate)
)
Now if you mark this column as computed in Entity Framework, it will refuse any updates to that column, because it'll know the database won't support that.
So the documentation for that attribute is incorrect or incomplete.
A column marked as Identity will use the database-specific syntax to generate a primary key for the given table when inserting a record, being IDENTITY() in MSSQL and AUTO_INCREMENT for MySQL. A computed column will simply be marked as read-only, and you'll have to provide your own implementation (either in the database or in your migration file) to specify the computation (see How to add computed column using migrations in code first?).

Entity Framework not claiming datetime.now is null

Here is my code:
UVCUpdate update = new UVCUpdate();
update.CurrentDate = DateTime.Now;
_context.UVCUpdates.Add(update);
_context.SaveChanges();
Now I am getting an inner exception though saying this:
Cannot insert the value NULL into column 'CurrentDate', table 'bLinked.dbo.BlackbookUpdateUVC'; column does not allow nulls. INSERT fails.
If I output the DateTime.Now just before this code it outputs:
9/15/2016 7:26:35 PM
My data type for CurrentDate in the db is set to datetime and in the class it is set to DateTime. Neither allow for nulls, but DateTime.Now should not be null right?
It almost always happens when there is mismatch between so called "store generated pattern" between EF model and database. If model column has store generated pattern of Identity or Computed - that means EF will be sure those values will be automatically provided by database on insert or update, and there is no need to include them in INSERT or UPDATE statements. Missing values will have default NULL value, and if this column is non-nullable in database at the same time, and is not really computed or identity - you have the error in question.
I am sorry guys, I feel like an idiot. Thank you to Leopard.
I went to get the UVCUpdate class to show him and realized that when I copied that class from another class I accidentally left [DatabaseGenerated(DatabaseGeneratedOption.Identity)] in the class for the CurrentDate. So it was likely attempting to send a null value to the SQL so the SQL would create an ID, but the field was set to not allow nulls. CurrentDate was not supposed to be an ID so I removed that and now it works...

Entity Framework 4 and SYSUTCDATETIME ()

I have a Table in my DataBase (MS SQL 2008) with a default value for a column SYSUTCDATETIME ().
The Idea is to automatically add Date and Time as soon as a new record is Created.
I create my Conceptual Model using EF4, and I have created an ASP.PAGE with a DetailsView Control in INSERT MODE.
My problems:
When I create a new Record. EF is not able to insert the actual Date and Time value but it inserts instead this value 0001-01-01 00:00:00.00.
I suppose the EF is not able to use SYSUTCDATETIME () defined in my DataBase
Any idea how to solve it? Thanks
Here my SQL script
CREATE TABLE dbo.CmsAdvertisers
(
AdvertiserId int NOT NULL IDENTITY
CONSTRAINT PK_CmsAdvertisers_AdvertiserId PRIMARY KEY,
DateCreated dateTime2(2) NOT NULL
CONSTRAINT DF_CmsAdvertisers_DateCreated DEFAULT sysutcdatetime (),
ReferenceAdvertiser varchar(64) NOT NULL,
NoteInternal nvarchar(256) NOT NULL
CONSTRAINT DF_CmsAdvertisers_NoteInternal DEFAULT ''
);
My Temporary solution:
Please guys help me on this
e.Values["DateCreated"] = DateTime.UtcNow;
More info here:
http://msdn.microsoft.com/en-us/library/bb387157.aspx
How to use the default Entity Framework and default date values
http://msdn.microsoft.com/en-us/library/dd296755.aspx
The problem is that EF doesn't know about that default value so it sends .NET default value to database. It is possible to force EF to use default value from DB but you must manually modify EDMX file (XML not designer). You must find column definition in SSDL part of EDMX and add StoreGeneratedPattern="Computed" attribute. You also must the same in CSDL part (this can be done in designer).
This setting will have several problems. First of all each update from database will delete your changes in SSDL. Also each insert and update will trigger select which will requery value from this column (because EF thinks that it is computed every time).
In your ASP .NET page when you create the record are you actually adding a value for the DateCreated value. I see that you are doing that now, which is what you needed to be doing in the first place.
So I would guess what was happening earlier is that you were creating your new record but not setting a value for the DateCreated Field. But since a DateTime has a default value of 0001-01-01 00:00:00.00 is why you were getting that behavior.
The default value would only work for the case where you insert a row but provide no indication of what to do with the DateCreated field. But the way that EF works it is always going to provide a value for this (unless you write your own insert query to override the generated ones).
You will also be potentially changing the value any time that you update the record as EF won't know what to do with it.

Categories