1

下一个代码运行时出现异常:

 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 不支持指定的类型成员“偏移”。仅支持初始化程序、实体成员和实体导航属性。

我的模型:

 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; }
}

有人可以帮助我吗?

4

5 回答 5

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 时,最好坚持使用支持的原始类型

于 2013-11-15T09:46:48.333 回答
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()。我想您必须根据您的上下文和其他要求来决定这是否可以接受,或者您是否必须寻找其他更好的解决方案。

于 2013-11-15T09:44:45.893 回答
1

以下代码可以a.MyDate.Offset在 Linq to Entities 查询中替换:

SqlFunctions.DatePart("TZoffset", a.MyDate)

请记住,这适用于 SqlServer。

于 2015-07-23T21:05:10.550 回答
0

问题是您不能直接访问DateTimeOffset.Offset属性 ( f.ClientTime.Offset),就像您不能DateTime.Year在 Linq 中直接访问属性到实体一样 - 它不能直接转换为存储表达式。

我不知道您f.FacebookUpdateTime - f.ClientTime.Offset <= DateTimeOffset.Now.UtcDateTime - ConvertTimeSpan(f.Offset)应该做什么,但是您可以查看静态SqlFunctions类以获取一些常见的日期操作函数SqlFunctions.DateDiff(),例如您可能可以用它替换整个表达式。

另外,您使用的是EF6吗?否则,您也必须将枚举转换为int

于 2013-11-15T10:11:53.820 回答
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 中进行过滤。但它会起作用。

于 2014-03-18T02:01:29.823 回答