在正在处理的应用程序中,我们为每个用户提供了一个选项,供他们选择自己的选项,timezone
并且在为特定用户显示数据时,我们会抓取timezone
他的选择并进行相应显示。现在,按照此处提到的答案,这确实是一个了不起的答案,我继续实现了上述选项,即按model
级别转换日期,并且按如下方式进行:
NotificationViewModel.cs
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; }
}
Repository.cs
GetUserTimeZoneDateTime
有2个重载
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);
}
在上述情况下的过载第一将被调用,但随后,从调用时model
电平,HttpContext.Current
将null
因此它失败。
在第二种方法中,我尝试过,timezone
将从控制器级别获取。
NotificationViewModel.cs
public class NotificationViewModel
{
public string Text { get; set; }
public DateTime Moment { get; set; }
public string Icon { get; set; }
}
TestController.cs
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);
}
var localTime = Repository.GetUserTimeZoneDateTime(context, DateTime.UtcNow);
datetime
根据首选用户获取适当的信息timezone
。但是然后Moment= Repository.GetUserTimeZoneDateTime(context,x.c_date),
里面linq expression
抛出错误如下
LINQ to Entities无法识别方法'System.DateTime GetUserTimeZoneDateTime(Direct_Commercial_Van.Models.EntityDataModel.dcvEntities,System.DateTime)'方法,并且该方法无法转换为商店表达式。
这是预期的。我还可以在这里尝试哪些其他选项来实现这一目标?或者如何以其他方式在这里处理时区问题?
在第一种情况下,您需要通过模型中的附加参数将HttpContext
(或User.Identity.Name
)注入模型(查看构造函数),然后从模型中注入(方法非常凌乱,不建议这样做)。
在第二种情况下,您需要先实现查询,然后再执行 .Select()
var p = context.tbl_prchs
.Where(...)
.ToList() // materialize query in in-memory set
.Select(x => new NotificationViewModel()
{
}).ToList();
但是,您的代码效率很低,因为您GetUserTimeZoneDateTime()
针对查询所返回的每一行(通过方法)调用数据库。您应该TimeZoneInfo
在调用查询之前更改代码以获取。
// 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();
或者,如果您不想首先实现查询,则可以将注入TimeZoneInfo
到您的视图模型中,然后将修改Moment
为计算所得的属性。
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); }
}
}
然后查询将是
....
var tZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(tZone);
var p = context.tbl_prchs
.Where(...)
.Select(x => new NotificationViewModel()
{
....
CDate = x.c_date,
TimeZoneInfo = tZoneInfo
}).ToList();
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句