I have a table that contains a LastUpdateOn
column, I would like to keep SQL Server current date & time (using GETDATE()
) in this column whenever I am doing insert or update operation in my table.
In ADO.NET, we used to call GETDATE()
function in insert/update statements, but how we can achieve the same thing using Entity Framework Core?
CodePudding user response:
There are two quick solutions for this on top of my head:
Simple put the value as default to GetDate() on this columns and pass null to EF when inserting or update;
Create a function that calls GetDate() before an inserting/update and use this as the value;
Edit:
- Create a new EF configuration for DateTime values that get the GetDate() function before inserting/update and automate the process;
CodePudding user response:
So as I moved away from stored procedures (where I used "GetDate()" or "CURRENT_TIMESTAMP" alot)... I embraced the c#/middleware layer.
I do a "null check" and set it on the c# code (in the entity framework data layer code)
Below shows DateTime. DateTime.MinValue means "somebody did not explicitly set it".
myEntityFrameworkEntity.InsertDate = parameterInsertDateValue == DateTime.MinValue ? DateTime.Now : parameterInsertDateValue;
There are other variations, but the idea is the same. Did the "caller" explicitly set the property, or did they not set it, let me write a value on their behalf.
Now, sometimes I don't care what the caller set. If it is a LastUpdatedDate , you can just "force it" as well (always set it to DateTime.Now)....
// i don't care what the parameters are, i always update it in this layer
myEntityFrameworkEntity.LastUpdatedDate = DateTime.Now;
Also, instead of using DateTime(.Now) directly... I use this:
https://github.com/vfabing/Chronos.Net
You "inject" a DateTime-PROVIDER .. that can be mocked for Unit-Tests.
Here is a more complete example to show my EF code (for Rest-Services that needs "disconnected" entities).
public const int ExpectedAddSingleOrUpdateSingleOrDeleteSingleSaveChangesAsyncRowCount = 1;
public async Task<EmployeeEfEntity> UpdateAsync(
EmployeeEfEntity inputEmployee,
CancellationToken token)
{
int saveChangesAsyncValue = 0;
/* find the object in the db-context using the object surrogate-primary-key (since this is an update) */
EmployeeEfEntity foundEntity =
await this.entityDbContext.EmployeeEfEntitys.FirstOrDefaultAsync(
item => item.EmployeeEfEntityKey == inputEmployee.EmployeeEfEntityKey,
token);
if (null != foundEntity)
{
/* update the found-entity with the properties of the input object */
/* the "normal" properties of the employee */
foundEntity.EmployeeBadgeNumber = inputEmployee.EmployeeBadgeNumber;
/* if the insert-date was explicit, use it, otherwise default to date-time.now */
foundEntity.InsertDate = inputEmployee.InsertDate == DateTime.MinValue ? DateTime.Now : inputEmployee.InsertDate;
/* we do not care about the input parameters, we always set it to "now" */
foundEntity.LastUpdated = inputEmployee.LastUpdated == DateTime.Now;
this.entityDbContext.Entry(foundEntity).State = EntityState.Modified;
saveChangesAsyncValue = await this.entityDbContext.SaveChangesAsync(token);
if (ExpectedAddSingleOrUpdateSingleOrDeleteSingleSaveChangesAsyncRowCount != saveChangesAsyncValue)
{
throw new ArgumentOutOfRangeException(
string.Format(ErrorMsgExpectedSaveChangesAsyncRowCount, saveChangesAsyncValue),
(Exception)null);
}
}
else
{
ArgumentOutOfRangeException argEx = new ArgumentOutOfRangeException(
string.Format(ErrorMsgPrimaryEntityNotFound, inputEmployee.EmployeeEfEntityKey),
(Exception)null);
this.logger.LogError(argEx);
}
return foundEntity;
}
My code actually uses the Chronos.Net (injected) date-time-provider, but I removed it to keep the code simpler for this answer.
CodePudding user response:
Since you're using Entity framework, which aimed at allowing database usage to be handled in C# more, I would just use DateTime.Now (DateTime.UtcNow if you want UTC time).
Set LastUpdateOn
to DateTime.Now
or DateTime.Utc.Now
each time you enter/upate a record.
If you really want to use SQL server's GETDATE()
method, then write a stored procedure that takes an interger (the id of the record to update) and use it to set LastUpdateOn
for the field with the specified id to the value of GETDATE()
.