How to manage GetDate() with Entity Framework - entity-framework

I have a column like this in 1 of my database tables
DateCreated, datetime, default(GetDate()), not null
I am trying to use the Entity Framework to do an insert on this table like this...
PlaygroundEntities context = new PlaygroundEntities();
Person p = new Person
{
Status = PersonStatus.Alive,
BirthDate = new DateTime(1982,3,18),
Name = "Joe Smith"
};
context.AddToPeople(p);
context.SaveChanges();
When i run this code i get the following error
The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value.\r\nThe statement has been terminated.
So i tried setting the StoreGeneratedPattern to computed... same thing, then identity... same thing. Any ideas?

You have to manually edit the edmx xml and set your SSDL StoreGeneratedPattern attributes to identity or computed. But whenever you update your edmx via the designer your changes will get overwritten.
This is a known issue. Please see the following links for more details:
Microsoft Connect Ticket
Using a GUID as an EntityKey in Entity Framework 4

I had the same problem! For me it works like this:
Database MS SQL Server express:
[RowTime] [datetime2](7) NOT NULL
ALTER TABLE [dbo].[Table_1] ADD CONSTRAINT [DF_Table_1_RowTime] DEFAULT (getdate()) FOR [RowTime]
GO
Then I import the table from database to my Entities model.
Entities will not realise the default value!
So, you have to set the StoreGeneratedPattern of the column to Computed.
Then Entities will not put there any default value any more.
Combination of:
datetime2,
NOT NULL,
StoreGeneratedPattern=Computed
Works for me!

Changing type of DateCreated to datetime2 might solve the problem.
datetime 2007-05-08 12:35:29.123
datetime2 2007-05-08 12:35:29. 12345
Ref: http://technet.microsoft.com/en-us/library/bb677335.aspx67

Here is a working workaround:
1) Change the column to datetime2 as mentioned elsewhere. This fixes the conversion error.
2) Add a trigger that sets DateCreated to getdate();
CREATE TRIGGER [TR_AS_ChangeTime] ON [AS_ApplicationSession]
AFTER INSERT,UPDATE AS
BEGIN
SET NOCOUNT ON;
UPDATE AS_ApplicationSession
SET AS_ChangeTime = getdate()
WHERE AS_Id IN(SELECT AS_ID FROM INSERTED)
END
3) If neccessary, set
p.DateCreated = DateTime.MinValue;
just to initialize it.
4) If you need the DateCreated from the database, add
context.Refresh(System.Data.Objects.RefreshMode.StoreWins, p);
just after
context.SaveChanges();

Focusing on the fact that I do not want change the database, since it is an application problem and I expect them to solve this problem one day, my solution (that is totally possible in my case) is to create a partial class of the model to correct the problem on constructor:
public partial class Log
{
public Log()
{
this.Date = DateTime.Now;
}
}
This works for me because:
I create the model on the moment I send it to database.
I use CLOUD for these services, the datetime must be the same in both Application and Database servers!
Don't forget that the namespace needs to match the Model namespace or partial should not list properties (and should no be partial as well ;])!

Related

Updating entity without having the know primary key

Given the following code, how can I add an element to one of the properties of an entity without knowing its Id and retrieving it from the database?
public async Task BookInPersonVisitAsync(Guid propertyId, DateTime dateTime, CancellationToken token)
{
var entity = new OnBoardingProcessEntity{ ExternalId = propertyId };
DbContext.OnBoardingProcesses.Attach(entity);
entity.OnBoardingProcessVisits.Add(new OnBoardingProcessVisitEntity
{
DateTime = dateTime,
Occurred = false
});
await DbContext.SaveChangesAsync(token);
}
ExternalId is just a guid we use for external reference. This doesnt work cause it does not have the id set, but without hitting the database we cant have it.
With entity framework if you have to reference an entity (referencedEntity) from another entity (entity) you have to know referencedEntity.
Otherwise you can add just add the entity setting the referencedEntity to null.
To know the referencedEntity or you know the Id or you have to retrieve it in some ways (from the database).
In SQL (DML) if (and only if) ExternalId is a candidate key noy nullable you can insert the OnBoardingProcessVisit record with a single roundtrip but the insert statement will contain an inner query.
OnBoardingProcessVisit.OnBoardingProcess_Id = (
SELECT
Id
FROM
OnBoardingProcess
WHERE
ExternalId = #propertyId)
EDIT
No way to generate that query with EF. You can have a look to external components (free and not free, for example EntityFramework Extended but in this case I think that doesn't help).
In this case I probably would try to use standard entity framework features (so 1 roundtrip to retrieve the OnBoardingProcess from the ExternalId).
Then, if the roundtrip is too slow, run the SQL query directly on the database.
About performances (and database consistency) add a unique index on OnBoardingProcess.ExternalId (in every case).
Another suggestion if you decide for the roundtrip.
In your code, the entity will be a proxy. If you don't disable lazy load, using your code you will do one more roundtrip when you will access to property
entity.OnBoardingProcessVisits (in the statement entity.OnBoardingProcessVisits.Add).
So, in this case, disable lazy load or do the same using a different way.
The different way in your case is something like
var onBoardingProcessVisitEntity new OnBoardingProcessVisitEntity
{
DateTime = dateTime,
Occurred = false,
OnBoardingProcess = entity
});
DbContext.OnBoardingProcessVisits.Add(onBoardingProcessVisitEntity);
await DbContext.SaveChangesAsync(token);

EF 6 database first: How to update stored procedures?

We are using Entity Framework 6.0.0 and use database first (like this) to generate code from tables and stored procedures. This seems to work great, except that changes in stored procedures are not reflected when updating or refreshing the model. Adding a column to a table is reflected, but not adding a field to a stored procedure.
It is interesting that if I go to the Model Browser, right click the stored procedure, select Add Function Import and click the button Get Column Information we can see the correct columns. This means that the model knows of the columns, but does not manage to update the generated code.
There is one workaround, and that is to delete the generated stored procedure before updating the model. This works as long as you have not made any edits on the stored procedure. Does anyone know of a way to avoid this workaround?
I am using Visual Studio 2013 with all the latest updates as of early December 2013.
Thanks in advance!
Update 1:
andersr's answer helped in one case, where the stored procedure used a temporary table, so i gave him +1, but it still does not solve the main problem of updating simple stored procedures.
Update 2:
shimron's comment below links to a question about the same issues in EF 3.5. It seems the same is still true for EF 6.0. Read it for an alternative way of doing it, but my conclusion as of now is that the simplest way of doing it is to delete the generated stored procedure before updating the model. Use partial classes if you want to do something fancy.
Based on this answer by DaveD, these steps address the issue:
In your .edmx, rt-click and select Model Browser.
Within the Model Browser (in VS 2015 default configuration, it is a tab within the Solution Explorer), expand Function Imports under the model.
Double-click your stored procedure.
Click the Update button next to Returns a Collection Of - Complex (if not returning a scalar or entity)
Click okay then save your .edmx to reflect field changes to your stored procedure throughout your project.
Does your stored procedures return data from temporary tables by any chance ? EF does not seem to support this, see EF4 - The selected stored procedure returns no columns for more information.
However, the stored procedure will as you observed, be available in the Model Browser. I did a quick test featuring the scenario described above. The stored procedure was generated in my context class, but the return type was an int rather than a complex type. See the link above for potential workarounds.
I just encountered this and my workaround (it is really nasty) was to create an if statement with a condition that will never be true at the top of the stored procedure which selects the same list of outputs as the query with explicit casting to the datatypes I want to return. This will assume nullability of your types, so to resolve that you wrap the cast in an ISNULL
For example, if your output has the columns:
UserId (int, not null)
RoleId (int, nullable)
FirstName (varchar(255), nullable)
Created (datetime, not null)
You would expect this to create a POCO like:
SomeClass {
public int UserId { get; set; }
public int? RoleId { get; set; }
public string FirstName { get; set; }
public DateTime Created { get; set; }
}
...But it doesn't and that's why we're here today. To get around this not working as expected, I put the following at the top of my SP (right after the 'AS'):
if(1=0)
begin
select
UserId = isnull((cast(0 as int)),0),
RoleId = cast(0 as int),
FirstName = cast(0 as varchar),
DateTime = isnull((cast(0 as datetime)),'')
end
It is horrible and ugly but it works for me every time. Hopefully we get a tooling update that resolves this soon...happened to me today with no temp tables in SQL Server 2016 w/VS2015...
Hope this helps somebody

Cannot insert explicit value for identity column in table 'LeistungGruppe' when IDENTITY_INSERT is set to OFF

I'm trying to add an EntityObject to my database by calling AddToLeistungGruppe.
LeistungGruppe in this case is my Table with Primary_Key LeistungGruppe_ID with Identity true and Identity increment 1 and seed 1.
I search a lot for this issue and alot of People got he same error.
They were told to simply set StoreGeneratedPattern to Identity and this would solve the Problem.
I tried it out and still got the same issue.
I'm new to the Entity Framework and have no idea about how to solve this Problem.
Somehow i think the model isn't updated probably because even if i Switch around These Settings I'm getting the same error over and over again.
Every help is appreciated.
You are trying to save an object to the database with an explicit ID set by you while the database is expecting to generate that value itself. That is the LeistungGruppe_ID property in your object is set to something other than 0 and it is not identified to the EF framework as an identity field. If you want the Id to be generated by the database as your post suggests, then the corresponding property in the Object should be decorated with the [Key] attribute.
If you are using the Fluent API then you should have something like this in your DBContext:
protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder)
{
modelBuilder.Entity<LeistungGruppe>().Property(x => x.LeistungGruppe_ID).StoreGeneratedPattern = StoreGeneratedPattern.Identity;
base.OnModelCreating(modelBuilder);
}

Entity Framework and Default Date

I have a table in SQL, within that table I have DateTime column with a default value of GetDate()
In entity framework I would like it to use the SQL date time instead of using the local date time of the computer the console app is running on (the SQL server is 1 hour behind).
The column does not allow nulls either, currently it passes in a date value of 1/1/0001 and I get an error:
The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value.\r\nThe statement has been terminated.
Thank you!
Open edmx designer
Select your DateTime column
Go to properties and change StoreGeneratedPattern from None to Computed
That will tell EF not to insert value for that column, thus column will get default value generated by database. Keep in mind that you will not be able to pass some value.
If you're using Fluent API, just add this to your DbContext class:
modelBuilder.Entity<EntityName>()
.Property(p => p.PropertyName)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
Set columnType for that entity in OnModelCreating Method:
modelBuilder.Entity().Property(s => s.ColumnName).HasColumnType("datetime2");

Problem with ConcurrencyCheck attribute approach in EF

I've found two ways of concurrency checking for my entities in EF 4.1:
TimeStamp attribute for byte array
ConcurrencyCheck attribute for another types
The first one is very simple. You just mark byte array property as TimeStamp, create additional column in database and voila...
I've got a problem with the second method. Enity Framework has started generate sql script for concurrency check, when I marked the LastUpdateDate property.
Property:
[ConcurrencyCheck]
public DateTime LastUpdateDate { get; set; }
Sql:
select
...
where (([Id] = #3) and ([LastUpdateDate] = #4))
...
#4='value'
But EF does not generate sql script for updating the value of LastUpdateDate?
Is it possible to say EF to update the LastUpdateDate after concurrency checking without triggers or something like this?
And the second question:
What is the best practice of using concurrency checking in EF when you have something like LastUpdateDate property(property will be displayed in UI)? Is it better to check concurency using LastUpdateDate and avoid creating of addtional column for TimeStamp in your tables or
create additional TimeStamp property and renounce of the using DateTime property for concurrency checking?
Have you tried to use a rowversion (timestamp) instead of the DateTime datatype to check for concurency?
I would use the timestamp, because you are sure that the system will update it for you. Further more the value will be very precice.
The following blog posts will give you more information about how to map a timestamp.
The first one shows how to use the timestamp as a concurrency check.
Code First Optimistic Concurrency with Fluent Assertions
Round tripping a timestamp field with EF4.1 Code First and MVC 3