我在下一个代码运行时遇到异常:
var fbPost = db.FacebookStatusUpdates
.Where(f =>
f.FacebookUpdateTime - f.ClientTime.Offset <=
DateTimeOffset.Now.UtcDateTime - ConvertTimeSpan(f.Offset) &&
f.Status == FacebookNotificationStatus.Active &&
f.Alarm.User.FbStatus == true).ToList();
异常消息
LINQ to Entities不支持指定的类型成员'Offset'。只要 初始化器,实体成员和实体导航属性是 支撑。
我的模特:
public class FacebookStatusUpdate
{
public long Id { get; set; }
public DateTime FacebookUpdateTime { get; set; }
public string PostId { get; set; }
public DateTime? FacebookPostTime { get; set; }
public DateTimeOffset ClientTime { get; set; }
public int Offset { get; set; }
public virtual FacebookNotificationStatus Status { get; set; }
public virtual Alarm Alarm { get; set; }
}
有人能帮助我吗?
答案 0 :(得分:6)
当您使用LINQ to Entities时,您需要记住您的查询将被转换为TSQL - 如果Offset
是自定义类型,那么EF不知道如何将其转换为SQL。
如果您可以将查询转换为LINQ to Objects,即
,您当然可以完成此工作 var fbPost = db.FacebookStatusUpdates
.Where(f => f.Status == FacebookNotificationStatus.Active &&
f.Alarm.User.FbStatus == true)
.AsEnumerable() // convert from L2E to L2O
.Where(f => f.FacebookUpdateTime - f.ClientTime.Offset <=
DateTimeOffset.Now.UtcDateTime - ConvertTimeSpan(f.Offset))
.ToList();
在调用AsEnumerable()
之后,查询的其余部分是LINQ to Objects,它们了解Offset
/ ConvertToTimespan
代码。只是为了澄清,AsEnumerable()
不会实现您的查询正确方式 - 您仍然会延迟加载。但是,在AsEnumerable()
完成客户端之后的任何进一步查询时,都不再与数据库进行交互。
使用L2E时,最好坚持使用受支持的primitive types。
答案 1 :(得分:1)
我怀疑这与您无法在Linq中直接使用标准C#方法和属性这一事实有关,因为db.FacebookStatusUpdates
中的数据最初可能无法加载。换句话说:该属性无法转换为SQL。
如果我的理解是正确的,这可能会为您提供解决方案:
var fbPost = db.FacebookStatusUpdates
.ToList() // <-- Forces evaluation/data retrieval!
.Where(f =>
f.FacebookUpdateTime - f.ClientTime.Offset <=
DateTimeOffset.Now.UtcDateTime - ConvertTimeSpan(f.Offset) &&
f.Status == FacebookNotificationStatus.Active &&
f.Alarm.User.FbStatus == true).ToList();
这将在尝试呼叫ClientTime.Offset
之前将数据加载到列表中,从而允许您进行该呼叫。
但是,在应用Where()
- 过滤之前,所有数据都已加载。我想你必须根据你的背景和其他要求决定这是否可以接受,或者你是否需要寻找其他更好的解决方案。
答案 2 :(得分:1)
以下代码可以替换Linq to Entities查询中的a.MyDate.Offset
:
SqlFunctions.DatePart("TZoffset", a.MyDate)
请记住,这与SqlServer一起工作。
答案 3 :(得分:0)
问题在于您无法直接访问DateTimeOffset.Offset
属性(f.ClientTime.Offset
),就像您无法直接在Linq中访问实体的DateTime.Year
属性一样 - 它可以不会直接翻译成商店表达。
我不知道你的f.FacebookUpdateTime - f.ClientTime.Offset <=
DateTimeOffset.Now.UtcDateTime - ConvertTimeSpan(f.Offset)
应该做什么,但你可以看一下静态SqlFunctions
类来处理一些常见的日期操作函数,比如SqlFunctions.DateDiff()
可以用。
另外,您使用的是EF6吗?否则你也必须将你的枚举投射到int
。
答案 4 :(得分:0)
您可以将查询分为两部分。
var fbPost_DBQuery = db.FacebookStatusUpdates
.Where(f => f.Status == FacebookNotificationStatus.Active &&
f.Alarm.User.FbStatus == true).ToList();
fbPost_MemoryQuery = fbPost_DBQuery
.Where(f => f.FacebookUpdateTime - f.ClientTime.Offset <=
DateTimeOffset.Now.UtcDateTime - ConvertTimeSpan(f.Offset))
.ToList();
fbPost_DBQuery将从数据库中查询更多信息,然后在fbPost_MemoryQuery中进行过滤。但它会奏效。