2011-08-26 61 views
2

应答时:去下面找我回答这个问题。使用日期比较查询的SharePoint OData服务

我试图使用LINQ的ASP.NET MVC 3项目消耗的SharePoint 2010的OData。我使用带有Razor视图引擎的ASP.NET MVC 3项目模板(VS 2010)创建了一个默认项目。我添加了一个指向我的SharePoint 2010网站的服务参考。

在我的HomeController的Index方法(这只是一个测试项目),我创建了一个变量来保存上下文和上下文变量的凭据属性设置为当前默认凭据。

像下面的链接查询工作正常,我可以使用创建的变量来访问任何数据:

var query = from a in context.Alerts 
      select a; 

这个查询只是获取所有的公告,从列表中的SharePoint网站称为警报。此列表包含标题,内容,开始日期和到期日期的字段。

当我查询更改为以下,我没有得到预期的结果:

var query = from a in context.Alerts 
      where (a.Begins < DateTime.Now) 
      select a; 

该查询忽略了日期的时间部分。例如,如果a.Begins包含昨天的日期时间,则查询将返回AlertItem。另一方面,如果a.Begins包含具有当前日期的日期时间(但是较早的时间),则比较返回false(并且a.Begins == DateTime.Now返回true)。

如果我这样做,第二LINQ查询按预期工作:

var query = (from a in context.Alerts 
      select a).ToList(); 
var query2 = from q in query 
      where (q.Begins < DateTime.Now) 
      select q; 

我缺少什么?

回答

0

从许多不同的来源拼凑的信息后 - 其中没有涉及,我有,我得出以下结论问题的确切情况:

当查询SharePoint数据使用SharePoint对象模型和协作应用程序标记语言(CAML),默认情况下SharePoint在进行比较时不使用DateTime元素的时间组件。要告诉的SharePoint使用时间组件,您必须包括IncludeTimeValue =“真”的值类型属性,如下所示:

<Where> 
<Eq> 
    <FieldRef Name='Begins' /> 
    <Value Type='DateTime' IncludeTimeValue='TRUE'> 
    2008-03-24T12:00:00Z 
    </Value> 
</Eq> 
</Where> 

我发现了几个博客帖子所引用的错误在LINQ到SharePoint引起的生成的CAML是输出为:

<Where> 
<Eq> 
    <FieldRef Name='dateTimeField' IncludeTimeValue='TRUE' /> 
    <Value Type='DateTime'> 
    2008-03-24T12:00:00Z 
    </Value> 
</Eq> 
</Where> 

注意,IncludeTimeValue =“TRUE”是FieldRef元件代替的价值元件上。由于这不是该属性的正确位置,因此它会导致执行日期时间比较的所有LINQ to SharePoint查询仅在日期组件上进行比较。

由于我在使用LINQ和WCF数据服务连接到SharePoint时看到完全相同的行为,因此我只能假定在下面的内容中,LINQ/WCF数据服务正在生成相同的无效CAML。

该解决方案(假设我仍然想使用LINQ/WCF数据服务)将执行两个查询(如原始问题中所述)。第一个LINQ查询从SharePoint抽取列表数据并将其存储在List中。第二个LINQ查询处理日期比较以仅提取我想要的数据。

由于我的特殊情况下,我可能会在SharePoint列表中的条目涵盖了较大的时间跨度,但将只关注在特定的一天或几天的条目,我想找到一种方法,不带回第一个查询中的整个列表。

我的定位是在做一个< =和> =比较来得到关闭,然后进一步限制在我的第二个查询。所以我的两个查询现在变成:

DateTime RightNow = DateTime.Now; 
var query = (from a in context.Alerts 
      where (a.Begins <= RightNow) && (a.Expires >= RightNow) 
      select a).ToList(); 
var query2 = from q in query 
      where q.Begins < RightNow) && (a.Expires > RightNow) 
      select q; 

第一LINQ语句将返回所有我最终感兴趣的项目;以及一些我不是(因为它只比较日期时间的日期组件)。第二条LINQ声明将进一步削减那些我感兴趣的内容。

0

是DateTime.Today的习惯有什么地方?我做了一些与LinqPad原型,并重复您的结果的唯一方法是,如果我有查询使用“其中(a.Begins < DateTime.Today)”

这是我做了什么它听起来像你的快速草图“再描述:

void Main() 
{ 
    List<Alerts> alerts = new List<Alerts>(); 
    alerts.Add(new Alerts(DateTime.Now.AddDays(-1))); 
    alerts.Add(new Alerts(DateTime.Now)); 

    var query = from a in alerts 
       where (a.Begins < DateTime.Now) 
       select a; 
    foreach (var element in query) 
    { 
     Console.WriteLine(element.Begins); 
    } 

} 
public class Alerts 
{ 
    public DateTime Begins {get; set;} 
    public Alerts(DateTime begins) 
    { 
     Begins = begins; 
    } 
} 

正如我所提到的,重复你所描述的结果是,如果我在where子句中改变DateTime.Now到DateTime.Today的唯一途径。我会查看你的代码是否意外地使用了错误的DateTime方法。另外,我强烈建议使用LinqPad进行Linq查询原型设计......通过允许您快速迭代代码并找出问题点的位置,它可以节省您的时间。另外,这对于智能感知和其他高级功能来说是非常值得的。

+0

号时,针对SharePoint 2010中的OData源未查询它工作得很好。我描述的行为仅在针对SharePoint 2010 OData源时才会发生。但要回答你的问题;不,我没有在任何地方使用DateTime.Today。 – RWGodfrey

+0

事实上,a.Begins == DateTime.Now是很奇怪的...另外,它听起来像一旦你有记录“在内存中”,即在第一个查询中,DateTime子句工作得很好......我想知道如果在DateTime周围有任何已知的OData问题? – Joe

+0

到目前为止,必应/谷歌/雅虎搜索小时以及更多小时的反复试验一无所获。我希望有人能够访问SharePoint 2010将运行类似的测试并报告其结果。 – RWGodfrey

1

我还没有使用SharePoint 2010的OData。但是,在查询SharePoint 2010对象模型时,发布的异常是一种常见行为,请注意:在查询数据之前,必须将查询转换为列表。

这里的典型模式是:

var query = someSharePointQuery.ToList(); 

var results = query.Where(...).First(...); 

似乎很奇怪,但这是SP 2010如何似乎工作。

0

我可以确认与SharePoint 2010 LINQ到SharePoint的错误不会创建正确的CAML(向FieldRef添加IncludeTimeValue ='True'的价值)由2013年10月的累积更新修复为SharePoint Foundation 2010.此修补程序可从http://technet.microsoft.com/en-us/sharepoint/ff800847.aspx下载。

在SharePoint 2013中我也收到了由Microsoft支持人员通知的相同错误应该在2013年12月累积更新到SharePoint Foundation 2013中得到解决,但我无法证实此问题。我被告知该修补程序也部署到Office 365,但我无法证实这一点。

2

对于需要包含DateTime的时间元素的Linq to SharePoint查询,可以使用TimeOfDay。

var next_slots = (from s in dc.HRDates 
        where 
        s.StartTime.HasValue && 
        s.StartTime.Value.Date == appt.Value.Date && 
        s.StartTime.Value.TimeOfDay == appt.Value.TimeOfDay 
        ...