After upgrade to EF Core 2.2 => 3.1, Guid ID no longer generated by DbSet.Add() - dotconnect

I'm upgrading from EF Core 2.2 to EF Core 3.1. I have an entity Patient with a GUID Id:
class Patient {
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
A DbSet is defined for this type:
public DbSet<Patient> Patients { get; set; }
In EF 2.2, when I added a new Patient, the Id would be automatically generated when the object was added to the DbSet:
// newPatient.Id -> 00000000-0000-0000-0000-000000000000
ctx.Patients.Add(newPatient);
// newPatient.Id -> C1D5ACB8-A4C9-4680-AF2F-BF5E5B0AC1B6 <=== GUID generated
Now, in EF 3.1, the Id is not being automatically generated upon Add:
// newPatient.Id -> 00000000-0000-0000-0000-000000000000
ctx.Patients.Add(newPatient);
// newPatient.Id -> 00000000-0000-0000-0000-000000000000 <=== still an empty GUID
This obviously breaks my code.
In EF Core 3.0 there is a breaking change "String and byte array keys are not client-generated by default". However, this breaking change indicates string and byte array keys, not GUID keys. Also, I have tried the recommended mitigations with FluentAPI and Data Annotations and it does not resolve my issue (still no GUID generated).
I am using the dotConnect for Oracle database provider v9.11. I did not find any breaking changes there that would affect this.
Of course I can explicitly assign a GUID Id in my code, but I'd like to make this work as it did before in EF Core 2.2.
Any suggestions why this is not working? Thanks.

Related

How to define the order of property deserialization when using ASP.NET Web API 2.2 OData V4

I would like to define the order of property deserialization when using ASP.NET Web API 2.2 OData V4. Perhaps there is already an attribute which can be used to define this. For the purpose of this e-mail I name it DeserializationOrderAttribute. I imagine I should be able to define a class like this:
public class Employee
{
[DeserializationOrder(0)]
public Guid EmployeeID { get; set; }
[DeserializationOrder(1)]
public string FirstName { get; set; }
[DeserializationOrder(1)]
public string LastName { get; set; }
}
In this situation, the EmployeeID property should be deserialized before FirstName and LastName. FirstName and LastName can be deserialized in any mutual order.
Is there an attribute for achieving this or is there another standard way of achieving definition of the order of property deserialization?
Best regards,
Henrik Dahl
You can add a DataMember attribute to your properties and then specify the Order property.
Note that properties not decorated with this attribute will always appear first as detailed here.

Azure Mobile Services table to c# class mismatch: Error: Item identifiers can only be specified via the 'id' property

I've just refactored my Xamarin Android app that uses Azure Mobile Services as backend. Recently I got this really strange error.
When I try to insert a new item to the database:
_client.GetTable<T>().InsertAsync(instance)
I then get a MobileServiceInvalidOperationException that goes:
Error: Item identifiers can only be specified via the 'id' property.
It seems like AMS is not able to match the class properties with the sql table. If I change Id to id then the next issue is that it cannot match __version with my property Version.
However the strange part is that it all works if I insert or read from the table at app startup (which I did before the refactoring). And only one table has this issue.
Does anyone have a clue what it could be? I could do a workaround by reading once at startup, but that's just not satisfying.
Here is the class / table.
using Microsoft.WindowsAzure.MobileServices;
using System;
namespace Core.Models
{
public class PostAction
{
public string Id { get; set; }
public string UserId { get; set; }
public string ImageURL { get; set; }
[CreatedAt]
public DateTime CreatedAt { get; set; }
[UpdatedAt]
public DateTime UpdatedAt { get; set; }
[Version]
public string Version { get; set; }
}
}
Try to change the data type from string to int for Id property.
Azure uses strings instead of ints as PKs. I you have old data in your app it might work up to a certain point since SQLite is pretty tolerant in terms of types. BUT at some point eg. if you used foreign key relations you will have to migrate your database.

Getting a the new value of RowVersion using Entity Framework 6

Is is possible, to get the new value of RowVersion using the same DbContext, without reloading the entity from the database?
Scenario:
Load data into editor form
Save new values
The row in the table gets updated, new value of RowVersion is generated
However, the saved entity still holds the old value of RowVersion, so the new value can not be passed back to the client
All concurrency control articles are usually concerned only with preventing the update (e.g. see this).
However, in the example from the article, a successful update is followed by a redirect to page, where the saved entity is read again and now it has a new RowVersion value. I would like to avoid this redirect.
Thanks to grennis, I found out the source of my problems.
I defined the interface and an entity like
public interface IRowVersion
{
// Attention: this will not be "inherited" by the implementing class !!!
[Timestamp]
byte[] VersionStamp { get; set; }
}
public class Directory : IRowVersion
{
[Key]
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
// If this attribute is missing here, then row version is used
// My initial version was without this attribute
[Timestamp]
public byte[] VersionStamp { get; set; }
}
In my problematic version, I thought that having the attribute on the interface property is enough. However, the attribute must be explicitly applied on the entity's property. Otherwise it will not be used at all (not even as the part of update SQL statement). The value was updated only because the DB updates the column value automatically and of course, at next read, I got the new value.
Not entirely related to the problem, but still worth mentioning... The following is really a killer feature of EF6
ctx.Database.Log = s => Debug.Write(s);
SQL Profiler, it was nice knowing you :-)

Insert values to entity framework in asp.net mvc4

In my asp.net mvc4 sample i have table in the name of Sample with three column as Name,Dept and Id.In this Id as identity and primary.I get a value for Name and Dept from user and insert that value to Sample table of entity framework.It pass value '0' to Id.And i got an error as "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".Please help me.
set "autoincrement" on the column and set the id as primary key in sql server ..
In EF code-first this is done by data annotations. Make sure you recreate your table (or database) after changing the scheme.
public class Sample
{
[Key]
[Required]
[Column(Order = 0)]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] //auto increment id
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int Dept { get; set; }
}
You don't need to pass an integer for Id. EF will resolve this automatically. Just create the object by filling in the name and the dept. By saving the changes to the database, EF will automatically fill in the auto generated Id.

An overflow occurred while converting to datetime using EF4

I have a windows application working with a SQL Compact 4.0 database, using EF 4.1 and code-first approach.
I cannot save an object to the database since I'm getting an exception, with inner exception
"An overflow occurred while converting to datetime"
when trying to save the type Quotation:
public class Quotation
{
public int ID { get; set; }
public string Name { get; set; }
public DateTime DateCreated { get; set; }
public ContactPerson ContactPersonAssigned { get; set; }
public string OurReference { get; set; }
public string QuotationDataString { get; set; }
}
I read that this error can be caused by a mismatch between my application settings and the sql compact database settings regarding the conversion of a date.
I'm not sure about it, since my sdf database file has a field which is correctly named "DateCreated", not-nullable and of type "datetime".
I'm new to SQL compact. Could you help me debug this problem?
If your model has non-nullable property of type DateTime, when you post a form with empty value for that property, it is automatically set to DateTime.MinValue, which is in .net 01/01/0001 (DateTime.MinValue on MSDN)
(As a side note, you can change this behavior by implementing your own IModelBinder for DateTime which could i.e. throw a validation exception if attempted value is null/empty and property is not nullable).
If you try to save that value (DateTime.MinValue) into database, you will get conversion error if database field is of sql type datetime, because .net DateTime.MinValue is less than SQL datetime minvalue (01/01/1753) and therefore cannot be converted to sql value. (SQL datetime min value on MSDN)
This error will not occur on newer versions of MS SQL Server, which have datetime2 datatype which allows values from 01/01/0001 to 31/12/9999 (SQL datetime2 on MSDN) (if datetime2 is used for that field, of course).
This is an old question ... but maybe somebody could find this helpful:
I solved the problem (MVC4, EF5, SqlServerCE 4.0) using following definition:
public DateTime? DateFrom { get; set; }
public DateTime? DateTo { get; set; }
Have fun!
I hade the same issue, the dateTime propety being saved on an object to the database was null initially.
Verify that an actually datetime has been assigned before saving the object to the local CE database.

Resources