2011-08-26 28 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 
        ...