Entity Framework not claiming datetime.now is null - c#

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...

Related

SQL DateTime field displays as DateTime? in C# classes created by Entity Framework

Through Visual Studio I have used Entity Framework to create classes corresponding to SQL Server Tables.
In the SQL Server table some fields are defined as "datetime" with a default value of (getutcdate()).
The Datetime fields in the C# classes that map to the database table datetime fields have an appended "?"
Click to see C# class
Can anyone tell me what this "?" means and if I need to do anything to prevent some looming disaster?
Grateful for any advice.
DateTime? is syntactical sugar for Nullable<DateTime>, which means that the value can store either a datetime, or null. A regular DateTime cannot store null, so developers may uses something like DateTime.Min to represent "no value set" (bad practice though).
The reason your generated classes have a DateTime? is likely because your column does not have NOT NULL constraint (different from a default value). I.e. since the server CAN store a NULL in the EntityDoB field, the generated class has to be able to handle a NULL date time in code.
The code won't fall over, and (assuming you can have a non-specified date) is correct. You just need to consider how Nullable's will impact your code, and be aware that Entity-Framework does not respect default database columns - if C# knows about the column, EF will specify a value.

problems with timestamp and concurrency

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.

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.

Using SqlServer uniqueidentifier/updated date columns with Linq to Sql - Best Approach

Rightly or wrongly, I am using unique identifier as a Primary Key for tables in my sqlserver database. I have generated a model using linq to sql (c#), however where in the case of an identity column linq to sql generates a unique key on inserting a new record for guid /uniqueidentifier the default value of 00000000-0000-0000-0000-000000000000.
I know that I can set the guid in my code: in the linq to sql model or elsewhere, or there is the default value in creating the sql server table (though this is overridden by the value generated in the code). But where is best to put generate this key, noting that my tables are always going to change as my solution develops and therefore I shall regenerate my Linq to Sql model when it does.
Does the same solution apply for a column to hold current datetime (of the insert), which would be updated with each update?
As you noted in you own post you can use the extensibility methods. Adding to your post you can look at the partial methods created in the datacontext for inserting and updating of each table. Example with a table called "test" and a "changeDate"-column:
partial void InsertTest(Test instance)
{
instance.idCol = System.Guid.NewGuid();
this.ExecuteDynamicInsert(instance);
}
partial void UpdateTest(Test instance)
{
instance.changeDate = DateTime.Now;
this.ExecuteDynamicUpdate(instance);
}
Thanks, I've tried this out and it seems to work OK.
I have another approach, which I think I shall use for guids: sqlserver default value to newid(), then in linqtosql set auto generated value property to true. This has to be done on each generation of the model, but this is fairly simple.
There's two things you can do:
either just generate the GUID in your C# client side code and use that value
create a DEFAULT constraint on the GUID column in SQL Server that defaults to newid() for the column - the SQL Server will make SURE to always add a default - unless you specify a value yourself
As for the self-updating date/time columns - here you probably have to use either client-side logic to do that, or if you want to do it on SQL Server, you'll have to write a trigger. That's really the only way to update a specific column everytime the row gets updated - there's no "autoupdate" constraint or anything like this (and the default constraint only work on INSERTs, not updates).
Something like this might work:
CREATE TRIGGER TRG_UpdateDateTimestamp
ON (your table name)
AFTER UPDATE
AS
IF NOT UPDATE(DateTimeStamp)
BEGIN
UPDATE (yourtablename)
SET DateTimeStamp = GETDATE()
WHERE EXISTS (SELECT * FROM inserted AS i
WHERE i.OID = (yourtable).OID)
END
Marc

System.Data.SqlTypes.SqlTypeException: SqlDateTime overflow

I am working with C#.net and also SQL Server 2008.
I have the following error, when trying to run a test unit within my project.
System.Data.SqlTypes.SqlTypeException:
SqlDateTime overflow. Must be between
1/1/1753 12:00:00 AM and 12/31/9999
11:59:59 PM..
Database Table
Column Name: createddate
Type: datetime
Default Value: (getdate())
Allow Nulls: No.
I don't want to insert the createddate as part of my INSERT query.
When I manually enter some data into the database table I get the following error:
The row was successfully committed
to the database. However, a problem
occurred when attempting to retrieve
the data back after commit. Because
of this the displayed data within the
row is read-only. To fix this
problem, please re-run the query.
I don’t understand why I am getting this error and cannot find anyone who has had this problem. Can anyone help?
Matt is most likely on the right track. You have defined a default value for your column - however, that will only take effect if you actually insert something in your table in the database.
When you do a unit test, as you say, you most likely initialize the DateTime variable to something (or not - then it'll be DateTime.MinValue, which is 01/01/0001) and then you send that to the SQL Server and this value is outside the valid range for a DATETIME on SQL Server (as the error clearly states).
So what you need to do is add a line to your .NET unit test to initialize the DateTime variable to "DateTime.Today":
DateTime myDateTime = DateTime.Today
and then insert that into SQL Server.
OR: you can change your SQL INSERT statement so that it does not insert a value for that column - it looks like right now, it does do that (and attempts to insert that - for SQL Server - invalid date into the table). If you don't specify that column in your INSERT, then the column default of getdate() will kick in and insert today's date into the column.
Marc
Are you using Linq to SQL to write your unit test?
If you are, it might be bypassing the getdate() default value, and using some other value instead which falls outside the valid range.
I got the same issue, I was using Linq with the DataClasses files automatically generated by VS2010.
The I realised that Linq is not using the default value (GetDate()) but it will send a Datetime.Min value. As the consequence the SQL server will reject this datetime "01/01/0001" because it's not in range.
What I did to fix it is to always set the value to Datetime.Now or Datetime.Today and so Linq will not send the bad Min Datetime value anymore.
You are probably getting an overflow error in your unit test because you are passing in an uninitialised DateTime with the value DateTime.MinValue which is outside the allowable range for SQL's datetime.
I think I have seen that error message when modifying the table manually, it isn't a problem, just refresh the table.
are you using a data context class setup with the DBML file and all that jazz? If so, then you can click on the field in your DBML file and set the "Auto Generated Value property" to True. Visual Studio must already know to do this with the Pkey fields, but has to be set for these "timestamping" sort of actions

Categories