如何指定从EntityFramework检索的DateTime对象应该是DateTimeKind.UTC

Wil*_*iam 28 c# datetime utc entity-framework-6

我有C#程序,所有DateTime对象都在这里DateTimeKind.UTC.将对象保存到数据库时,它按预期存储UTC.但是,当他们撤回时,他们就是DateTimeKind.Unspecified.有没有办法告诉实体框架(代码优先)DateTime在C#中创建对象时总是使用DateTimeKind.UTC

And*_*ena 19

不,没有.它实际上是DateTimeKind.Unspecified.

但是,如果您担心支持多个时区,则应考虑使用DateTimeOffset.它就像一个常规的DateTime,除了它不代表时间的"视角",它代表一个绝对视图,其中3PM(UTC - 3)等于4PM(UTC - 2).DateTimeOffset包含DateTime和时区,并且EntityFramework和SQL Server都支持它.

  • `DateTimeOffset`*不包含时区:它包含创建值的时刻的*UTC偏移*.它有更多关于实际值的信息,但它几乎没有比一个简单的UTC`DateTime`值更有用.如果你想要一个相对于时区的值,你必须将该时区存储在某处并转换该值,就像你对`DateTime`一样. (10认同)

Jon*_*nna 7

你可以让你的datacontext修复所有相关的值.以下是实体类型的属性缓存,以避免每次都检查类型:

public class YourContext : DbContext
{
  private static readonly List<PropertyInfo> EmptyPropsList = new List<PropertyInfo>();
  private static readonly Hashtable PropsCache = new Hashtable(); // Spec promises safe for single-reader, multiple writer.
                                                                  // Spec for Dictionary makes no such promise, and while
                                                                  // it should be okay in this case, play it safe.
  private static List<PropertyInfo> GetDateProperties(Type type)
  {
    List<PropertyInfo> list = new List<PropertyInfo>();
    foreach(PropertyInfo prop in type.GetProperties())
    {
      Type valType = prop.PropertyType;
      if(valType == typeof(DateTime) || valType == typeof(DateTime?))
        list.Add(prop);
    }
    if(list.Count == 0)
      return EmptyPropsList; // Don't waste memory on lots of empty lists.
    list.TrimExcess();
    return list;
  }
  private static void FixDates(object sender, ObjectMaterializedEventArgs evArg)
  {
    object entity = evArg.Entity;
    if(entity != null)
    {
      Type eType = entity.GetType();
      List<PropertyInfo> rules = (List<PropertyInfo>)PropsCache[eType];
      if(rules == null)
        lock(PropsCache)
          PropsCache[eType] = rules = GetPropertyRules(eType); // Don't bother double-checking. Over-write is safe.
      foreach(var rule in rules)
      {
        var info = rule.PropertyInfo;
        object curVal = info.GetValue(entity);
        if(curVal != null)
          info.SetValue(entity, DateTime.SpecifyKind((DateTime)curVal, rule.Kind));
      }
    }
  }
  public YourContext()
  {
    ((IObjectContextAdapter)this).ObjectContext.ObjectMaterialized += FixDates;
    /* rest of constructor logic here */
  }
  /* rest of context class here */
}
Run Code Online (Sandbox Code Playgroud)

这也可以与属性结合使用,以便DateTimeKind通过存储关于每个属性的一组规则,而不仅仅是PropertyInfo,并在其中查找属性,来设置每个属性应该具有的属性GetDateProperties.