Fetching timezone based on user logged in with httpcontext asp.net mvc
在我正在处理的应用程序中,我们为每个用户提供了一个选项,可以选择他们自己的
NotificationViewModel.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class NotificationViewModel { public string Text{ get; set; } public DateTime Moment { get { return _Created; } set { _Created = Repository.GetUserTimeZoneDateTime(value); } } private DateTime _Created { get; set; } public string Icon { get; set; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public static DateTime GetUserTimeZoneDateTime(DateTime dTime) { using (var context = new EntityContext()) { var tZone = context.tbl_usrs.AsNoTracking().FirstOrDefault(x => x.uname == HttpContext.Current.User.Identity.Name).preferred_timezone; var tZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(tZone); return TimeZoneInfo.ConvertTimeFromUtc(dTime, tZoneInfo); } } public static DateTime GetUserTimeZoneDateTime(EntityContext context, DateTime dTime) { var tZone = context.tbl_usrs.AsNoTracking().FirstOrDefault(x => x.uname == HttpContext.Current.User.Identity.Name).preferred_timezone; var tZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(tZone); return TimeZoneInfo.ConvertTimeFromUtc(dTime, tZoneInfo); } |
在上面的例子中,将调用第一个重载,但是当从
在第二种方法中,我尝试过,
NotificationViewModel.cs
1 2 3 4 5 6 | public class NotificationViewModel { public string Text { get; set; } public DateTime Moment { get; set; } public string Icon { get; set; } } |
TestController.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | using (var context = new EntityContext()) { var localTime = Repository.GetUserTimeZoneDateTime(context, DateTime.UtcNow); List<NotificationViewModel> model = new List<NotificationViewModel>(); int days = DateTime.UtcNow.DayOfWeek - DayOfWeek.Sunday; DateTime weekStart = localTime.AddDays(-days); DateTime weekEnd = weekStart.AddDays(6); var p = context.tbl_prchs .Where(x => x.c_date <= weekEnd && x.c_date >= weekStart) .Select(x => new NotificationViewModel() { Icon ="fa fa-gbp", Moment = Repository.GetUserTimeZoneDateTime(context,x.c_date), Text ="Test notes", }).ToList(); model.AddRange(p); } |
LINQ to Entities does not recognize the method 'System.DateTime
GetUserTimeZoneDateTime(Direct_Commercial_Van.Models.EntityDataModel.dcvEntities,
System.DateTime)' method, and this method cannot be translated into a
store expression.
这是预料之中的。还有什么其他选择可以在这里尝试实现这一目标?或者我在其他方面如何处理时区问题?
在第一种情况下,您需要将
在第二种情况下,您需要在
1 2 3 4 5 6 | var p = context.tbl_prchs .Where(...) .ToList() // materialize query in in-memory set .Select(x => new NotificationViewModel() { }).ToList(); |
但是,您的代码效率非常低,因为您为查询返回的每一行调用数据库(通过
1 2 3 4 5 6 7 8 9 10 11 12 | // Get the time zone info var tZone = context.tbl_usrs.AsNoTracking().......' var tZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(tZone); // Generate the view model var p = context.tbl_prchs .Where(...) .ToList() // materialize query in in-memory set .Select(x => new NotificationViewModel() { .... Moment = TimeZoneInfo.ConvertTimeFromUtc(x.c_date, tZoneInfo); }).ToList(); |
或者,如果您不想首先实现查询,则可以将
1 2 3 4 5 6 7 8 9 10 11 | public class NotificationViewModel { public string Text { get; set; } public DateTime CDate { get; set; } public string Icon { get; set; } public TimeZoneInfo TimeZoneInfo { get; set; } public DateTime Moment { get { return TimeZoneInfo.ConvertTimeFromUtc(CDate, TimeZoneInfo); } } } |
然后查询将是
1 2 3 4 5 6 7 8 9 10 | .... var tZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(tZone); var p = context.tbl_prchs .Where(...) .Select(x => new NotificationViewModel() { .... CDate = x.c_date, TimeZoneInfo = tZoneInfo }).ToList(); |