是否有一种方法可以指示Entity Framework始终将DateTimeOffset存储为UTC值。从技术上讲,没有理由这样做但我更喜欢它,如果我的数据库中的所有数据都是一致的。
目前它正在存储从客户端收到的DateTimeOffset,它可以是任何东西,具体取决于用户的区域设置。
我在考虑拦截所有的SaveChanges方法,循环更改,查找DateTimeOffset类型并明确地进行转换,但是如果EntityFramework内置了一些内容,这似乎可以减轻很多工作。
非常感谢任何见解或建议。
编辑:我的帖子与处理此主题的其他人之间的区别在于我的C#属性是DateTimeOffset类型,我的数据库字段也是DateTimeOffset(0)。除了一致性之外,没有技术理由进行转换。如果我将值存储为" 17:00 +5:00"或" 10:00 -2:00"没关系,这些都是相同的时刻。但是,我希望将所有日期存储为" 12:00 +0:00"这样在SSMS或其他数据库工具中更容易阅读。
编辑2:看起来似乎没有"简单"我希望现在解决DbContext.SaveChanges()函数中的问题。问题在于,无论我做什么,价值都不会改变?这是迄今为止的代码:
public new void SaveChanges()
{
foreach (var entry in this.ChangeTracker.Entries())
{
foreach (var propertyInfo in entry.Entity.GetType().GetProperties().Where(p => p.CanWrite && p.PropertyType == typeof(DateTimeOffset)))
{
var value = entry.CurrentValues.GetValue<DateTimeOffset>(propertyInfo.Name);
var universalTime = value.ToUniversalTime();
entry.CurrentValues[propertyInfo.Name] = universalTime;
// entry.Property(propertyInfo.Name).CurrentValue = universalTime;
// Adding a watch to "entry.CurrentValues[propertyInfo.Name]" reveals that it has not changed??
}
// TODO: DateTimeOffset?
}
base.SaveChanges();
}
编辑3 我终于设法解决了这个问题,请参阅下面的答案
答案 0 :(得分:0)
这样的东西?
Activator
答案 1 :(得分:0)
感谢我收到的帮助。由于Jcl
,我终于找到了答案public new void SaveChanges()
{
foreach (var entry in this.ChangeTracker.Entries().Where(p => p.State == EntityState.Added || p.State == EntityState.Modified))
{
foreach (var propertyInfo in entry.Entity.GetType().GetTypeProperties().Where(p => p.PropertyType == typeof(DateTimeOffset)))
{
propertyInfo.SetValue(entry.Entity, entry.CurrentValues.GetValue<DateTimeOffset>(propertyInfo.Name).ToUniversalTime());
}
foreach (var propertyInfo in entry.Entity.GetType().GetTypeProperties().Where(p => p.PropertyType == typeof(DateTimeOffset?)))
{
var dateTimeOffset = entry.CurrentValues.GetValue<DateTimeOffset?>(propertyInfo.Name);
if (dateTimeOffset != null) propertyInfo.SetValue(entry.Entity, dateTimeOffset.Value.ToUniversalTime());
}
}
base.SaveChanges();
}
修改强>
根据Jcl的建议,我写了一个小助手来缓存反射:
public static class TypeReflectionExtension
{
public static Dictionary<Type, PropertyInfo[]> PropertyInfoCache;
static TypeReflectionHelper()
{
PropertyInfoCache = new Dictionary<Type, PropertyInfo[]>();
}
public static PropertyInfo[] GetTypeProperties(this Type type)
{
if (!PropertyInfoCache.ContainsKey(type))
{
PropertyInfoCache[type] = type.GetProperties();
}
return PropertyInfoCache[type];
}
}
编辑2: 为了清理代码,我创建了一个通用函数,您可以使用它来拦截和修改任何数据类型:
public static class DbEntityEntryExtension
{
public static void ModifyTypes<T>(this DbEntityEntry dbEntityEntry, Func<T, T> method)
{
foreach (var propertyInfo in dbEntityEntry.Entity.GetType().GetTypeProperties().Where(p => p.PropertyType == typeof(T) && p.CanWrite))
{
propertyInfo.SetValue(dbEntityEntry.Entity, method(dbEntityEntry.CurrentValues.GetValue<T>(propertyInfo.Name)));
}
}
}
这个用法是(在你的DbContext里面):
public new void SaveChanges()
{
foreach (var entry in this.ChangeTracker.Entries().Where(p => p.State == EntityState.Added || p.State == EntityState.Modified))
{
entry.ModifyTypes<DateTimeOffset>(ConvertToUtc);
entry.ModifyTypes<DateTimeOffset?>(ConvertToUtc);
}
base.SaveChanges();
}
private static DateTimeOffset ConvertToUtc(DateTimeOffset dateTimeOffset)
{
return dateTimeOffset.ToUniversalTime();
}
private static DateTimeOffset? ConvertToUtc(DateTimeOffset? dateTimeOffset)
{
return dateTimeOffset?.ToUniversalTime();
}
<强>声明强> 这确实解决了我的问题,但不推荐。我甚至不知道我是否会使用它,因为现在感觉不对(感谢Jcl;)。所以请谨慎使用。您可以通过Adam Benson
按照答案更好