根据用户使用httpcontext登录的时间获取asp.net mvc
在我们的应用程序中,我们有一个选项供每个用户选择他们自己的timezone
,当显示特定用户的数据时,我们提取timezone
选择他并相应地显示。现在,作为每答案mentioned here,这实在是一个真棒一个,我继续在model
一级执行上面提到的选项,即日期的转换,我已经按以下步骤进行的:根据用户使用httpcontext登录的时间获取asp.net mvc
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实体无法识别方法“的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();
获取'只有无参数的构造函数和初始化器在LINQ to Entities.'异常兄弟中受支持.. :(另外,我正在使用'ToListAsync()':(忘记提及.. –
在这种情况下,您需要实现查询第一(但除非你查询返回成千上万的行,它没有什么可担心的)但我会尽快编辑答案,以显示一个替代方案,我认为应该工作 –
肯定好友.. :) –
对于第二一个,物化查询你打电话之前'。选择()'即 - '变种P = context.tbl_prchs.Where(.. ..)。ToList()。Select({...})。ToList();' –
那么,这将是一个不错的选择,但不会是性能开销? –
另外,有没有什么办法可以处理'ToListAsync()'而不是'ToList()'? –