Currently, I am storing theDateTime with the DeliveryDate getter/setter. However, I'm having issues storing this in UTC time. I've done some research on this and tried DateTimeKind.Utc but can't get that to work correctly. How can I get DeliveryDate to store the DateTime in UTC time?
My Code:
public partial class shippingInfo
{
public System.Guid EmailConfirmationId {get; set; }
public Nullable<System.DateTime> DeliveryDate {get; set; }
}
Update: Added Implementation:
DeliveryExpirationRepository.Add(new DeliveryPendingConfirmation
{
EmailConfirmationId = newGuid,
DeliveryDate = DateTime.Now.AddHours(48),
});
To make a DateTime store a UTC value, you must assign it a UTC value. Note the use of DateTime.UtcNow instead of DateTime.Now:
DeliveryExpirationRepository.Add(new DeliveryPendingConfirmation
{
EmailConfirmationId = newGuid,
DeliveryDate = DateTime.UtcNow.AddHours(48),
});
The DateTime.UtcNow documentation says:
Gets a DateTime object that is set to the current date and time on this computer, expressed as the Coordinated Universal Time (UTC).
The DateTime.Now documentation says:
Gets a DateTime object that is set to the current date and time on this computer, expressed as the local time.
You might want to use DateTimeOffset instead. It always stores an absolute point in time, unambiguously.
You can add a code to the setter method to check if value is not in UTC and convert this value to UTC:
public class shippingInfo {
public System.Guid EmailConfirmationId { get; set; }
private Nullable<System.DateTime> fDeliveryDate;
public Nullable<System.DateTime> DeliveryDate {
get { return fDeliveryDate; }
set {
if (value.HasValue && value.Value.Kind != DateTimeKind.Utc) {
fDeliveryDate = value.Value.ToUniversalTime();
}
else {
fDeliveryDate = value;
}
}
}
}
In this case, you don't need to care how a value of this property is set. Or you can use the DateTime.ToUniversalTime method to convert any date to UTC where you set a value of the property.
Related
StartTime
AgentId
08/19/2021 07:04:56 AM UTC
33
08/11/2021 02:58:35 PM IST
42
08/12/2021 01:01:51 AM CST
24
08/12/2021 08:52:34 PM UTC
61
public class MyModel
{
public string StartTime { get; set; }
public int AgentId { get; set; }
public string TimeZone { get; set; }
public string Time { get; set; }
}
I have the above C# Class model MyModel and its sample data stored as a List<MyModel> in my logic. I need a help to parse the StartTime field of a list such that, the TimeZone field should get the UTC/CST/IST of its corresponding StartTime and Time field of a list should be time stamp from its StartTime i,e: 07:04:56 or 02:58:35 and so on. Finally the list should look like something like below:
StartTime
AgentId
Time
TimeZone
08/19/2021 07:04:56 AM UTC
33
07:04:56 AM
UTC
08/11/2021 02:58:35 PM IST
42
02:58:35 PM
IST
08/12/2021 01:01:51 AM CST
24
01:01:51 AM
CST
08/12/2021 08:52:34 PM UTC
61
08:52:34 PM
UTC
Given the fact that all of the segments in your StartTime property have a forced amount of characters thanks to the string format you've chosen (except for the timezone where we could have e.g. CEST but we don't have to worry about that and I'll get to the why in just a second) we can simply use the String.Substring method and for the first parameter, define the character from where the newly to be outputted string should start reading and as the second parameter, the amount of characters it should read from there on out. If we don't set the second parameter the String.Substring method will simply read the string to the very end and since the timezone is the last segment of the StartTime format, the unknown amount of characters for the timezone is no problem for us.
With that in mind, here are some options you can choose from:
If you don't want to adjust your class:
private void ManageMyModels(List<MyModel> models)
{
models.ForEach(model =>
{
model.TimeZone = model.StartTime.Substring(23);
model.Time = model.StartTime.Substring(11, 11);
});
}
This solution is pretty simple as it just iterates over every MyModel element and sets the TimeZone and Time property values accordingly to the StartTime value. However, it would be a lot nicer if we didn't always had to do this manually for every model we create so here's a better solution if you don't mind adjusting your class:
public class MyModel
{
public string StartTime { get; set; }
public int AgentId { get; set; }
public string TimeZone => this.StartTime.Substring(23);
public string Time => this.StartTime.Substring(11, 11);
}
The way this solution works is, whenever you access either the TimeZone or Time property, its assigned code will be executed returning the substring that you need. Performance wise there would be a disadvantage where the code would be executed every time you call either of the properties even when the StartTime value hasn't changed.
Alternatively you could do it the other way around where every time you pass a new value to the StartTime both of the properties would be updated as well:
public class MyModel
{
private string _startTime;
public string StartTime
{
get => _startTime;
set
{
this._startTime = value;
this.TimeZone = value.Substring(23);
this.Time = value.Substring(11, 11);
}
}
public int AgentId { get; set; }
public string TimeZone { get; private set; }
public string Time { get; private set; }
}
This eliminates previously mentioned disadvantage but creates a new one where the TimeZone and Time property will always be updated whenever the StartTime property is, even if you wouldn't use it.
Personally, I'd stick to the previous option simply because it's shorter and easier to read.
I've read a bunch about auto implemented properties but I still don't quite get it. I have and entity:
public class News
{
public int NewsId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public DateTime Date { get; set; }
}
Now I don't want the user to set date himself every time a new entity of News type is created. I want the record to be saved automatically with the datetime it's created. Thinking about it I suggest that it's enough to just modify the set for my property to something like :
public DateTime Date
{
get;
set
{
Date = DateTime.Now;
}
}
But reading about the topic I saw that the standard way is to create private variable and use it instead in the implementation. That's where I get a little bit lost.
private DateTime _date = null;
public DateTime Date
{
Well I'm not sure for the getter and setter implementations. It seems reasonable to have something like : set { _date = DateTime.Now;} and I have no idea how to deal with the get part since I want this data to be fetched from the database so something like : get {return _date;} doesn't make much sense to me even though almost every example with auto implementedset` returns the private variable. But I think that if the property is an entity this is not making a lot of sense.
Some ways to return the current date:
public DateTime Date { get { return DateTime.Now; } }
or
public class News
{
public News()
{
Date = DateTime.Now;
}
public DateTime Date { get; private set; }
}
The first one will always return the current date/time, even if that instance was created some time ago. The second one will return the date/time the instance was created. Both prevent the user from setting that Date value.
You could add a constructor to your class and then initialize there your property.
public class News
{
// properties goes here
public News()
{
Date=DateTime.Now;
}
}
A far better constructor would be the following
public News(int newsId, string title, string content)
{
NewsId=newsId;
Title=title;
Content=content;
Date=DateTime.Now;
}
That way you could create an object of type News in a single line of code.
News news = new News(1,"title1","whatever");
Don't touch the getter and setter! They are auto generated from a template and will be overridden every once and a while. Instead, as you might have noticed the generated entities are declared partially, create a partial class and declare a constructor there that sets the _date or Date of you r entity to DateTime.Now on construction (just as you desired).
public partial class News
{
public News()
{
this.Date = DateTime.Now;
}
}
I have a system that takes information from an external source and then stores it to be displayed later.
One of the data items is a date. On the source system they have the concept of a fuzzy date i.e. not accurate to a specific day or sometimes not to a month as well. So I get dates in the format:
dd/mm/yyyy
mm/yyyy
yyyy
I can parse these to DateTime objects and work with these but when rendering later I need to be able to determine the accuracy of the date since parsing "2010" will result in a date of "01/01/2010". I want to show just the year so need to know it's original accuracy.
I've mocked up a quick class to deal with this:
public class FuzzyDate
{
public DateTime Date { get; set; }
public DateType Type { get; set; }
}
public enum DateType
{
DayMonthYear,
MonthYear,
Year
}
This will do the job for me and I can do something on the parse to handle it but I feel like this is probably quite a common problem and there is probably an existing cleaner solution.
Is there something built into .Net to do this? I had a look at the culture stuff but that didn't quite seem right.
Any help would be appreciated.
To answer your question: There is nothing built into .NET to handle this gracefully.
Your solution is as valid as any I've seen. You will probably wish to embellish your class with overrides to the ToString() method that will render your date appropriately based on the DateType.
Here are a couple other threads that attempt to address this question:
Strategy for Incomplete Dates
Implementing a "Partial Date" object
Good luck!
If your data type will always handle specific periods of time (i.e. the year 1972 is a specific period of time, but the 4th of July is not specific), you can store your data as a start time and time span.
If your date was "1972", the start date would be 19720101 and the time span would be 366 days.
If your date was "07/1972", the start date would be 19720701 and the time span would be 31 days.
If your date was "04/07/1972", the start date would be 19720704 and the time span would be 1 day.
Here's a possible implementation:
public struct VagueDate
{
DateTime start, end;
public DateTime Start { get { return start; } }
public DateTime End { get { return end; } }
public TimeSpan Span { get { return end - start; } }
public VagueDate(string Date)
{
if (DateTime.TryParseExact(Date, "yyyy", null, 0, out start))
end = start.AddYears(1);
else if (DateTime.TryParseExact(Date, "MM/yyyy", null, 0, out start))
end = start.AddMonths(1);
else if (DateTime.TryParseExact(Date, "dd/MM/yyyy", null, 0, out start))
end = start.AddDays(1);
else
throw new ArgumentException("Invalid format", "Date");
}
public override string ToString()
{
return Start.ToString("dd/MM/yyyy") + " plus " + Span.TotalDays + " days";
}
}
As I started to read your problem, I rapidly came to the conclusion that the answer was to implement your own FuzzyDate class. Lo and behold, that's exactly what you've done.
I can imagine that you might want to add functionality to this over time (such as comparisons that take into account the DateType).
I don't believe there's anything that will inherently help you in the .NET Framework, so I think you're doing the right thing.
I think you're going down the right route. There is no concept of a 'fuzzy' date or partial date, you will need to build your own.
You will likely need more constructor methods, for example
public FuzzyDate(int year)
{
Date = new DateTime(year,1,1); // 1 Jan yy
Type = DateType.Year;
}
public FuzzyDate(int year, int month)
{
Date = new DateTime(year, month, 1); // 1 mm yy
Type = DateType.MonthYear;
}
public FuzzyDate(int year, int month, int day)
{
Date = new DateTime(year, month, day); // dd mm yy
Type = DateType.DayMonthYear;
}
Hope this helps,
Kevin
It seems to me that your approach is right. Its true that .NET DateTime support multiple formats but I guess that given that all of them are supported with a concept of steps (nanoseconds), then will be related to specific date AND time.
One thing I would do differently is use null-able values (or use -1 for null semantics) for month and day to indicate what data was collected. Then I would have a factory method that would take a DateType param and return a DateTime. This method would throw and exception if only the year was available and the client code tried to create a DateType.DayMonthYear.
public class FuzzyDate
{
int _year;
int? _month;
int? _day;
public DateTime Date { get; set; }
public DateType Type { get; set; }
public DateTime GetDateTime(DateType dateType) { // ...
}
public enum DateType
{
DayMonthYear,
MonthYear,
Year
}
This might seem a bit over the top but the approach would explicitly store the original data and only represent "faked" DateTime objects when requested. If you were to persist a DateTime object internally along with a DateType enum you would lose some resolution.
As far as I am aware there is nothing built into .NET for this, the solution I'd go for is one based upon nullable values, something like this.
public class FuzzyDate
{
private int Year;
private int? Month;
private int? Day;
public FuzzyDate(int Year, int? Month, int? Day)
{
this.Year = Year;
this.Month = Month;
this.Day = Day;
}
public DateType DateType
{
get
{
if(Day.HasValue && Month.HasValue)
{
return DateType.DayMonthYear;
}
else if(Month.HasValue)
{
return DateType.MonthYear;
}
else
{
return DateType.Year;
}
}
}
public DateTime Date
{
get
{
return new DateTime(Year, Month.GetValueOrDefault(1), Day.GetValueOrDefault(1));
}
}
}
public enum DateType
{
DayMonthYear,
MonthYear,
Year
}
You could create your own structure (user-defined type) based on the datetime that would allow 00 for month, and 00 for day... And then also implement icomparable, so you can do math/comparrisons on it.
http://msdn.microsoft.com/en-us/library/k69kzbs1%28v=vs.71%29.aspx
http://msdn.microsoft.com/en-us/library/system.icomparable.aspx
I need help converting this string --> 20090727 10:16:36:643 to --> 07/27/2009 10:16:36
The original date and time are being returned by the SynchronizationAgent.LastUpdated() function, which returns a String in the above format.
Original question:preserved for reference
I have this -->
HUD.LastSyncDate = mergeSubscription.SynchronizationAgent.LastUpdatedTime;
Which is setting a property that looks like this -->
public static string LastSyncDate
{
get { return _lastSyncDate; }
set
{
_lastSyncDate = String.Format(CultureInfo.InvariantCulture,"{0:G}", value);
}
}
Unfortunately, with or without the String.Format the date that is displayed looks like this --> 20090727 10:16:36:643
I have tried multiple variations to Format it the way I want. What am I missing?
Based on the below suggestions(Mostly Joel's), I implemented the suggested changes but I am still getting a "String is not a valid DateTime error"
I also tried implementing this -->
HUD.LastSyncDate = DateTime.ParseExact(mergeSubscription.SynchronizationAgent.LastUpdatedTime,"yyyyMMdd HH:mm:ss:fff",CultureInfo.InvariantCulture);
but still nothing.
HUD.LastSyncDate = DateTime.Parse(mergeSubscription.SynchronizationAgent.LastUpdatedTime).ToString("MM/dd/yyyy")
You can put any format string you want there. But it sounds like what you really want is something more like this:
private static DateTime _lastSyncDate;
public static DateTime LastSyncDate
{
get { return _lastSyncDate; }
set { _lastSyncDate = value;}
}
public static string LastSyncDateString
{
get { return LastSyncDate.ToString("MM/dd/yyyy"); }
}
Keep it as a datetime in the background and just use the string property for display.
It appears to me that LastUpdatedTime is actually a string (since you can do the assignment) not a DateTime. In that case, the format applied won't do anything. You'll want to parse the LastUpdatedTime into a DateTime then reformat into the format that you want before assigning it to your string.
DateTime lastUpdated = DateTime.Parse( mergeSubscription.SynchronizationAgent.LastUpdatedTime );
HUD.LastSyncDate = string.Format( "{0:G}", lastUpdated );
public static string LastSyncDate { get; set; }
Note that you may need to use ParseExact instead.
DateTime lastUpdated = DateTime.ParseExact( "yyyyMMdd HH:mm:ss:fff",
...,
CultureInfo.InvariantCulture );
What do you want to do? You get a string, pass it to String.Format() and store it in a string field. Do you want to reformat the string? In this case you have to parse the string back to DateTime and format this value again.
DateTime dateTime;
if (DateTime.TryParse(value, out dateTime))
{
lastSyncDate = String.Format(CultureInfo.InvariantCulture,"{0:G}", dateTime);
}
else
{
HandleInvalidInput(value);
}
Does any one know how I can specify the Default value for a DateTime property using the System.ComponentModel DefaultValue Attribute?
for example I try this:
[DefaultValue(typeof(DateTime),DateTime.Now.ToString("yyyy-MM-dd"))]
public DateTime DateCreated { get; set; }
And it expects the value to be a constant expression.
This is in the context of using with ASP.NET Dynamic Data. I do not want to scaffold the DateCreated column but simply supply the DateTime.Now if it is not present. I am using the Entity Framework as my Data Layer
Cheers.
You cannot do this with an attribute because they are just meta information generated at compile time. Just add code to the constructor to initialize the date if required, create a trigger and handle missing values in the database, or implement the getter in a way that it returns DateTime.Now if the backing field is not initialized.
public DateTime DateCreated
{
get
{
return this.dateCreated.HasValue
? this.dateCreated.Value
: DateTime.Now;
}
set { this.dateCreated = value; }
}
private DateTime? dateCreated = null;
Add below to the DateTime property
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
I have tested this on EF core 2.1
Here you cannot use either Conventions or Data Annotations. You must use the Fluent API.
class MyContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.Property(b => b.Created)
.HasDefaultValueSql("getdate()");
}
}
Official doc
There's no reason I can come up with that it shouldn't be possible to do through an attribute. It might be in Microsoft's backlog. Who knows.
The best solution I have found is to use the defaultValueSql parameter in the code first migration.
CreateTable(
"dbo.SomeTable",
c => new
{
TheDateField = c.DateTime(defaultValueSql: "GETDATE()")
});
I don't like the often reference solution of setting it in the entity class constructor because if anything other than Entity Framework sticks a record in that table, the date field won't get a default value. And the idea of using a trigger to handle that case just seems wrong to me.
It is possible and quite simple:
for DateTime.MinValue
[System.ComponentModel.DefaultValue(typeof(DateTime), "")]
for any other value as last argument of DefaultValueAttribute specify string that represent desired DateTime value.
This value must be constant expression and is required to create object (DateTime) using TypeConverter.
Just found this looking for something different, but in the new C# version, you can use an even shorter version for that:
public DateTime DateCreated { get; set; } = DateTime.Now;
A simple solution if you are using the Entity Framework is the add a partical class and define a constructor for the entity as the framework does not define one. For example if you have an entity named Example you would put the following code in a seperate file.
namespace EntityExample
{
public partial class Example : EntityObject
{
public Example()
{
// Initialize certain default values here.
this._DateCreated = DateTime.Now;
}
}
}
I think the easiest solution is to set
Created DATETIME2 NOT NULL DEFAULT GETDATE()
in column declaration and in VS2010 EntityModel designer set corresponding column property StoreGeneratedPattern = Computed.
Creating a new attribute class is a good suggestion. In my case, I wanted to specify 'default(DateTime)' or 'DateTime.MinValue' so that the Newtonsoft.Json serializer would ignore DateTime members without real values.
[JsonProperty( DefaultValueHandling = DefaultValueHandling.Ignore )]
[DefaultDateTime]
public DateTime EndTime;
public class DefaultDateTimeAttribute : DefaultValueAttribute
{
public DefaultDateTimeAttribute()
: base( default( DateTime ) ) { }
public DefaultDateTimeAttribute( string dateTime )
: base( DateTime.Parse( dateTime ) ) { }
}
Without the DefaultValue attribute, the JSON serializer would output "1/1/0001 12:00:00 AM" even though the DefaultValueHandling.Ignore option was set.
Simply consider setting its value in the constructor of your entity class
public class Foo
{
public DateTime DateCreated { get; set; }
public Foo()
{
DateCreated = DateTime.Now;
}
}
using System.ComponentModel.DataAnnotations.Schema;
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime CreatedOn { get; private set; }
I needed a UTC Timestamp as a default value and so modified Daniel's solution like this:
[Column(TypeName = "datetime2")]
[XmlAttribute]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:yyyy-MM-dd}")]
[Display(Name = "Date Modified")]
[DateRange(Min = "1900-01-01", Max = "2999-12-31")]
public DateTime DateModified {
get { return dateModified; }
set { dateModified = value; }
}
private DateTime dateModified = DateTime.Now.ToUniversalTime();
For DateRangeAttribute tutorial, see this awesome blog post
There is a way. Add these classes:
DefaultDateTimeValueAttribute.cs
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using Custom.Extensions;
namespace Custom.DefaultValueAttributes
{
/// <summary>
/// This class's DefaultValue attribute allows the programmer to use DateTime.Now as a default value for a property.
/// Inspired from https://code.msdn.microsoft.com/A-flexible-Default-Value-11c2db19.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public sealed class DefaultDateTimeValueAttribute : DefaultValueAttribute
{
public string DefaultValue { get; set; }
private object _value;
public override object Value
{
get
{
if (_value == null)
return _value = GetDefaultValue();
return _value;
}
}
/// <summary>
/// Initialized a new instance of this class using the desired DateTime value. A string is expected, because the value must be generated at runtime.
/// Example of value to pass: Now. This will return the current date and time as a default value.
/// Programmer tip: Even if the parameter is passed to the base class, it is not used at all. The property Value is overridden.
/// </summary>
/// <param name="defaultValue">Default value to render from an instance of <see cref="DateTime"/></param>
public DefaultDateTimeValueAttribute(string defaultValue) : base(defaultValue)
{
DefaultValue = defaultValue;
}
public static DateTime GetDefaultValue(Type objectType, string propertyName)
{
var property = objectType.GetProperty(propertyName);
var attribute = property.GetCustomAttributes(typeof(DefaultDateTimeValueAttribute), false)
?.Cast<DefaultDateTimeValueAttribute>()
?.FirstOrDefault();
return attribute.GetDefaultValue();
}
private DateTime GetDefaultValue()
{
// Resolve a named property of DateTime, like "Now"
if (this.IsProperty)
{
return GetPropertyValue();
}
// Resolve a named extension method of DateTime, like "LastOfMonth"
if (this.IsExtensionMethod)
{
return GetExtensionMethodValue();
}
// Parse a relative date
if (this.IsRelativeValue)
{
return GetRelativeValue();
}
// Parse an absolute date
return GetAbsoluteValue();
}
private bool IsProperty
=> typeof(DateTime).GetProperties()
.Select(p => p.Name).Contains(this.DefaultValue);
private bool IsExtensionMethod
=> typeof(DefaultDateTimeValueAttribute).Assembly
.GetType(typeof(DefaultDateTimeExtensions).FullName)
.GetMethods()
.Where(m => m.IsDefined(typeof(ExtensionAttribute), false))
.Select(p => p.Name).Contains(this.DefaultValue);
private bool IsRelativeValue
=> this.DefaultValue.Contains(":");
private DateTime GetPropertyValue()
{
var instance = Activator.CreateInstance<DateTime>();
var value = (DateTime)instance.GetType()
.GetProperty(this.DefaultValue)
.GetValue(instance);
return value;
}
private DateTime GetExtensionMethodValue()
{
var instance = Activator.CreateInstance<DateTime>();
var value = (DateTime)typeof(DefaultDateTimeValueAttribute).Assembly
.GetType(typeof(DefaultDateTimeExtensions).FullName)
.GetMethod(this.DefaultValue)
.Invoke(instance, new object[] { DateTime.Now });
return value;
}
private DateTime GetRelativeValue()
{
TimeSpan timeSpan;
if (!TimeSpan.TryParse(this.DefaultValue, out timeSpan))
{
return default(DateTime);
}
return DateTime.Now.Add(timeSpan);
}
private DateTime GetAbsoluteValue()
{
DateTime value;
if (!DateTime.TryParse(this.DefaultValue, out value))
{
return default(DateTime);
}
return value;
}
}
}
DefaultDateTimeExtensions.cs
using System;
namespace Custom.Extensions
{
/// <summary>
/// Inspired from https://code.msdn.microsoft.com/A-flexible-Default-Value-11c2db19. See usage for more information.
/// </summary>
public static class DefaultDateTimeExtensions
{
public static DateTime FirstOfYear(this DateTime dateTime)
=> new DateTime(dateTime.Year, 1, 1, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond);
public static DateTime LastOfYear(this DateTime dateTime)
=> new DateTime(dateTime.Year, 12, 31, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond);
public static DateTime FirstOfMonth(this DateTime dateTime)
=> new DateTime(dateTime.Year, dateTime.Month, 1, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond);
public static DateTime LastOfMonth(this DateTime dateTime)
=> new DateTime(dateTime.Year, dateTime.Month, DateTime.DaysInMonth(dateTime.Year, dateTime.Month), dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond);
}
}
And use DefaultDateTimeValue as an attribute to your properties. Value to input to your validation attribute are things like "Now", which will be rendered at run time from a DateTime instance created with an Activator. The source code is inspired from this thread: https://code.msdn.microsoft.com/A-flexible-Default-Value-11c2db19. I changed it to make my class inherit with DefaultValueAttribute instead of a ValidationAttribute.
I faced the same issue, but the one which works for me best is below:
public DateTime CreatedOn { get; set; } = DateTime.Now;
In C# Version 6 it's possible to provide a default value
public DateTime fieldname { get; set; } = DateTime.Now;
Using EntityTypeConfiguration, I get it like this:
public class UserMap : IEntityTypeConfiguration<User>
{
public void Configure(EntityTypeBuilder<User> builder)
{
//throw new NotImplementedException();
builder.Property(u => u.Id).ValueGeneratedOnAdd();
builder.Property(u => u.Name).IsRequired().HasMaxLength(100);
builder.HasIndex(u => u.Email).IsUnique();
builder.Property(u => u.Status).IsRequired();
builder.Property(u => u.Password).IsRequired();
builder.Property(u => u.Registration).HasDefaultValueSql("getdate()");
builder.HasMany(u => u.DrawUser).WithOne(u => u.User);
builder.ToTable("User");
}
}
Using the Fluent API, in OnModelCreating function in your Context class add following.
builder.Property(u => u.CreatedAt).ValueGeneratedOnAdd();
builder.Property(u => u.UpdatedAt).ValueGeneratedOnAddOrUpdate();
Note I'm using a separate type configuration class. If you did right in the function would be like:
builder.Enitity<User>().Property(u => u.CreatedAt).ValueGeneratedOnAdd();
public DateTime DateCreated
{
get
{
return (this.dateCreated == default(DateTime))
? this.dateCreated = DateTime.Now
: this.dateCreated;
}
set { this.dateCreated = value; }
}
private DateTime dateCreated = default(DateTime);
How you deal with this at the moment depends on what model you are using Linq to SQL or EntityFramework?
In L2S you can add
public partial class NWDataContext
{
partial void InsertCategory(Category instance)
{
if(Instance.Date == null)
Instance.Data = DateTime.Now;
ExecuteDynamicInsert(instance);
}
}
EF is a little more complicated see http://msdn.microsoft.com/en-us/library/cc716714.aspx for more info on EF buisiness logic.
I know this post is a little old, but a have a suggestion that may help some.
I used an Enum to determine what to set in the attribute constructor.
Property declaration :
[DbProperty(initialValue: EInitialValue.DateTime_Now)]
public DateTime CreationDate { get; set; }
Property constructor :
Public Class DbProperty Inherits System.Attribute
Public Property InitialValue As Object
Public Sub New(ByVal initialValue As EInitialValue)
Select Case initialValue
Case EInitialValue.DateTime_Now
Me.InitialValue = System.DateTime.Now
Case EInitialValue.DateTime_Min
Me.InitialValue = System.DateTime.MinValue
Case EInitialValue.DateTime_Max
Me.InitialValue = System.DateTime.MaxValue
End Select
End Sub
End Class
Enum :
Public Enum EInitialValue
DateTime_Now
DateTime_Min
DateTime_Max
End Enum
I think you can do this using StoreGeneratedPattern = Identity (set in the model designer properties window).
I wouldn't have guessed that would be how to do it, but while trying to figure it out I noticed that some of my date columns were already defaulting to CURRENT_TIMESTAMP() and some weren't. Checking the model, I see that the only difference between the two columns besides the name is that the one getting the default value has StoreGeneratedPattern set to Identity.
I wouldn't have expected that to be the way, but reading the description, it sort of makes sense:
Determines if the corresponding column in the database will be auto-generated during insert and update operations.
Also, while this does make the database column have a default value of "now", I guess it does not actually set the property to be DateTime.Now in the POCO. This hasn't been an issue for me as I have a customized .tt file that already sets all of my date columns to DateTime.Now automatically (it's actually not hard to modify the .tt file yourself, especially if you have ReSharper and get a syntax highlighting plugin. (Newer versions of VS may already syntax highlight .tt files, not sure.))
The issue for me was: how do I get the database column to have a default so that existing queries that omit that column will still work? And the above setting worked for that.
I haven't tested it yet but it's also possible that setting this will interfere with setting your own explicit value. (I only stumbled upon this in the first place because EF6 Database First wrote the model for me this way.)
below works in .NET 5.0
private DateTime _DateCreated= DateTime.Now;
public DateTime DateCreated
{
get
{
return this._DateCreated;
}
set { this._DateCreated = value; }
}
You can also consider using the DatabaseGenerated attribute, example
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public DateTime DateCreated { get; set; }
https://learn.microsoft.com/en-us/ef/core/modeling/generated-properties?tabs=data-annotations
I also wanted this and came up with this solution (I'm only using the date part - a default time makes no sense as a PropertyGrid default):
public class DefaultDateAttribute : DefaultValueAttribute {
public DefaultDateAttribute(short yearoffset)
: base(DateTime.Now.AddYears(yearoffset).Date) {
}
}
This just creates a new attribute that you can add to your DateTime property.
E.g. if it defaults to DateTime.Now.Date:
[DefaultDate(0)]