可以实体框架自动将datetime字段转换为UTC吗? [英] Can Entity Framework automatically convert datetime fields to UTC on save?

查看:144
本文介绍了可以实体框架自动将datetime字段转换为UTC吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用ASP.NET MVC 5编写应用程序。我将要存储在数据库中的所有datetime必须首先从本地时区转换为UTC时区。



我不知道请求周期中最好的地方在哪里。



我可以在控制器通过后将每个字段转换为UTC ViewModel规则。但是我觉得这是一个太多的代码/步骤,我必须做。



在实体框架中有一种方法将允许我添加一个自动转换日期时间的规则保存更改前的UTC到UTC?



这是我写的将把日期时间转换为UTC的方法

  public static DateTime? ConvertToUTC(DateTime?val,TimeZoneInfo destinationTimeZone = null)
{
if(val!= null)
{
var dateTimeToConvert = ConvertToDateTime(val);

if(destinationTimeZone == null)
{
if(ConfigurationManager.AppSettings [LocalTimeZone]!= null)
{
destinationTimeZone = TimeZoneInfo .FindSystemTimeZoneById(ConfigurationManager.AppSettings [LocalTimeZone]);
}
else
{
destinationTimeZone = TimeZoneInfo.FindSystemTimeZoneById(TimeZone.CurrentTimeZone.StandardName);
}
}
返回TimeZoneInfo.ConvertTimeFromUtc(dateTimeToConvert,destinationTimeZone);

}

返回null;
}


解决方案


在实体框架中有一种方法,允许我在保存更改之前添加一个自动将datetime转换为UTC的规则。


您可以覆盖SaveChanges / SaveChangesAsync方法,并在DbContext上调用之前执行转换。

  //在您的DbContext类型

public override int SaveChanges(){
DateTimeUtcHelper.SetDatesToUtc(this.ChangeTracker.Entries());
return base.SaveChanges();
}

class DateTimeUtcHelper {
内部静态void SetDatesToUtc(IEnumerable< DbEntityEntry>更改){
foreach(var dbEntry in changes.Where(x => ChangesToTrackList .Contains(new [] {EntityState.Added,EntityState.Modified}))){
foreach(dbEntry.CurrentValues.PropertyNames中的var propertyName){

//使用反射添加逻辑确定它是一个DateTime还是可以为null的DateTime
//&&&如果它的种类= DateTimeKind.Local或未指定
//然后转换设置Utc值
//并将其写回到使用dbEntry.CurrentValues [propertyName] = utcvalue的条目;

}
}
}
}

您需要添加自己的逻辑,以确保不会在不是来自用户的更改中更改DateTime的实例(例如,确保默认情况下,您的实例化DateTimes具有DateTimeKind.Utc标志设置或本地,如果您为用户更改它。)






修改



DbContext还需要访问该运行的请求上下文的用户配置文件中的时区。也许SaveChanges的重载可能会更好,以便您可以将其传递或者如果您使用DI,或许您可以将其注入到创建的DbContext中。


I am writing an application using ASP.NET MVC 5. All of my datetime that I am going to store in the database must be converted from local time zone to UTC timezone first.

I am not sure where is the best place to do during the request cycle.

I can convert each field to UTC in the controller after it passes the ViewModel rules. But I feel this is too much code/step that I have to do.

Is there a way in Entity Framework that will allow me to add a rule that automatically converts datetime to UTC before saving the changes?

This is the method that I wrote that will convert a giving datetime to UTC

public static DateTime? ConvertToUTC(DateTime? val, TimeZoneInfo destinationTimeZone = null)
{
        if (val != null)
        {
            var dateTimeToConvert = ConvertToDateTime(val);

            if (destinationTimeZone == null)
            {
                if (ConfigurationManager.AppSettings["LocalTimeZone"] != null)
                {
                    destinationTimeZone = TimeZoneInfo.FindSystemTimeZoneById(ConfigurationManager.AppSettings["LocalTimeZone"]);
                }
                else
                {
                    destinationTimeZone = TimeZoneInfo.FindSystemTimeZoneById(TimeZone.CurrentTimeZone.StandardName);
                }
            }
            return TimeZoneInfo.ConvertTimeFromUtc(dateTimeToConvert, destinationTimeZone);

        }

        return null;
}

解决方案

Is there a way in Entity Framework that will allow me to add a rule that automatically converts datetime to UTC before saving the changes?

You can override the SaveChanges / SaveChangesAsync methods and execute conversion before those get called on the DbContext.

// on your DbContext type

public override int SaveChanges(){
    DateTimeUtcHelper.SetDatesToUtc(this.ChangeTracker.Entries());
    return base.SaveChanges();
}

class DateTimeUtcHelper{
    internal static void SetDatesToUtc(IEnumerable<DbEntityEntry> changes) {
        foreach (var dbEntry in changes.Where(x => ChangesToTrackList.Contains(new[] {EntityState.Added, EntityState.Modified}))){
            foreach (var propertyName in dbEntry.CurrentValues.PropertyNames){

                // using reflection add logic to determine if its a DateTime or nullable DateTime
                // && if its kind = DateTimeKind.Local or Unspecified
                // and then convert set the Utc value
                // and write it back to the entry using dbEntry.CurrentValues[propertyName] = utcvalue;

            }
        }
    }
}

You would need to add your own logic to ensure there are not instances where you are changing the DateTime on a change that did not come from a user (ie. make sure that by default your materialized DateTimes have the DateTimeKind.Utc flag set or .Local if you change it for the user).


Edit

The DbContext would also need access to the timezone on the users profile for that Request context that it is running in. Perhaps an overload of SaveChanges would be better suited so you can pass it in OR if you are using DI perhaps you could inject it into the created DbContext.

这篇关于可以实体框架自动将datetime字段转换为UTC吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆