2012-02-21 93 views
1

我正在使用SPMetal爲我的SharePoint站點生成實體類,但我不完全確定當有多種內容類型時最佳實踐是什麼爲單個列表。例如,我有一個任務列表,其中包含2種內容類型,我通過SPMetal的配置文件定義它們。這裏是我的定義...LINQ to Sharepoint單個列表的多種內容類型

<List Member="Tasks" Name="Tasks"> 
    <ContentType Class="LegalReview" Name="LegalReviewContent"/>  
    <ContentType Class="Approval" Name="ApprovalContent"/>  
</List> 

這似乎在生成的對象工作得很好也從WorkflowTask但對於數據的背景下產生的類型繼承是WorkflowTask的名單。所以當我做一個查詢時,我得到一個WorkflowTask對象而不是LegalReview或Approval對象。我如何讓它返回正確類型的對象?

[Microsoft.SharePoint.Linq.ListAttribute(Name="Tasks")] 
public Microsoft.SharePoint.Linq.EntityList<WorkflowTask> Tasks { 
    get { 
     return this.GetList<WorkflowTask>("Tasks"); 
    } 
} 

UPDATE 感謝回去我。我不知道如何重新創建基於SPListItem的類型,並希望得到任何反饋。

ContractManagementDataContext context = new ContractManagementDataContext(_url); 
WorkflowTask task = context.Tasks.FirstOrDefault(t => t.Id ==5); 
Approval a = new Approval(task.item); 

public partial class Approval{ 
    public Approval(SPListItem item){ 
     //Set all properties here for workflowtask and approval type? 
     //Wouldn't there be issues since it isn't attached to the datacontext? 
    } 

    public String SomeProperty{ 
     get{ //get from list item}; 
     set{ //set to list item}; 
} 

回答

2

Linq2SharePoint將始終爲列表中的所有ContentType返回第一個公共基ContentType的對象。這不僅僅是因爲必須使用某種描述的基本類型來組合代碼中的不同ContentType,而且它只會映射應該在列表中的所有ContentType上肯定存在的字段。但是可以訪問由L2SP返回的底層SPListItem,從而決定ContentType並向下轉換該項目。

由於是從T4模板生成自定義存儲庫層的一部分,我們有一個局部除了由SPMetal生成的項目類,它實現ICustomMapping獲得不一般的L2SP實體可用的數據。在下面的簡化版本中,獲取ContentType和ModifiedDate以顯示方法;儘管我們使用的完整類也映射了修改者,創建日期/依據,附件,版本,路徑等,但所有原則都是一樣的。

public partial class Item : ICustomMapping 
{ 
private SPListItem _SPListItem; 
public SPListItem SPListItem 
{ 
    get { return _SPListItem; } 
    set { _SPListItem = value; } 
} 
public string ContentTypeId { get; internal set; } 
public DateTime Modified { get; internal set; } 

public virtual void MapFrom(object listItem) 
{ 
    SPListItem item = (SPListItem)listItem; 
    this.SPListItem = item; 
    this.ContentTypeId = item.ContentTypeId.ToString(); 
     this.Modified = (DateTime)item["Modified"]; 
} 

public virtual void MapTo(object listItem) 
{ 
    SPListItem item = (SPListItem)listItem; 
     item["Modified"] = this.Modified == DateTime.MinValue ? this.Modified = DateTime.Now : this.Modified; 
} 

public virtual void Resolve(RefreshMode mode, object originalListItem, object databaseObject) 
{ 
    SPListItem originalItem = (SPListItem)originalListItem; 
    SPListItem databaseItem = (SPListItem)databaseObject; 

     DateTime originalModifiedValue = (DateTime)originalItem["Modified"]; 
     DateTime dbModifiedValue = (DateTime)databaseItem["Modified"]; 

    string originalContentTypeIdValue = originalItem.ContentTypeId.ToString(); 
    string dbContentTypeIdValue = databaseItem.ContentTypeId.ToString(); 

    switch(mode) 
    { 
     case RefreshMode.OverwriteCurrentValues: 
       this.Modified = dbModifiedValue; 
      this.ContentTypeId = dbContentTypeIdValue; 
      break; 

     case RefreshMode.KeepCurrentValues: 
       databaseItem["Modified"] = this.Modified; 
      break; 

     case RefreshMode.KeepChanges: 
       if (this.Modified != originalModifiedValue) 
       { 
        databaseItem["Modified"] = this.Modified; 
       } 
       else if (this.Modified == originalModifiedValue && this.Modified != dbModifiedValue) 
       { 
        this.Modified = dbModifiedValue; 
       } 
      if (this.ContentTypeId != originalContentTypeIdValue) 
      { 
       throw new InvalidOperationException("You cannot change the ContentTypeId directly"); 
      } 
      else if (this.ContentTypeId == originalContentTypeIdValue && this.ContentTypeId != dbContentTypeIdValue) 
      { 
       this.ContentTypeId = dbContentTypeIdValue; 
      }     
      break; 
    } 
} 
} 

一旦你將contentType和底層SPListItem您L2SP實體可用時,它是簡單地寫從基本類型的值的組合返回派生的ContentType實體實例的方法的問題,並SPListItem的缺失字段的額外數據。

更新:我實際上沒有示例轉換器類,因爲我們沒有以這種方式使用上述映射擴展項。不過我能想象這樣的事情會的工作:

public static class EntityConverter 
{ 
    public static Approval ToApproval(WorkflowTask wft) 
    { 
     Approval a = new Approval(); 
     a.SomePropertyOnWorkflowTask = wft.SomePropertyOnWorkflowTask; 
     a.SomePropertyOnApproval = wft.SPListItem["field-name"]; 
     return a; 
    } 
} 

或者你可以把在WorkflowTask的部分實例的方法返回一個審批對象。

public partial class WorkflowTask 
    { 
     public Approval ToApproval() 
     { 
      Approval a = new Approval(); 
      a.SomePropertyOnWorkflowTask = this.SomePropertyOnWorkflowTask; 
      a.SomePropertyOnApproval = this.SPListItem["field-name"]; 
return a; 
     } 

     public LegalReview ToLegalReview() 
     { 
      // Create and return LegalReview as for Approval 
     } 
    } 

在這兩種情況下,你需要確定的方法調用來從WorkflowTask的ContentTypeId屬性派生類型。這是我通常希望以某種形式生成的代碼,因爲它會非常重複,但這有點偏離主題。

+0

嗨Rob感謝您的反饋,一個很好的戰略,以獲得底層的SPListItem。我仍然不確定你將如何創建一個給定列表項目的實體......是否會像更新後的問題一樣? – 2012-02-22 22:02:54

+0

是的,你可以做那樣的事情。不需要直接從SPListItem中提取值的附加屬性,因爲您將在創建對象時初始化實體上的屬性。你對這個實體沒有被附加到上下文也是正確的。我沒有包含它,因爲它取決於需求,但如果您需要更新/刪除,則可以將實體附加到合適的上下文中。還有其他方法可以降低,例如一個靜態的EntityConverter類或每個基類型的方法。讓我知道如果你需要一個例子,我會更新答案。 – robwilliams 2012-02-23 12:16:09

+0

嗨,Rob,如果你能發佈你的entityconverter類的例子,如果它對你來說不是太多工作,我會很感激。再次感謝所有的幫助! – 2012-02-23 16:47:47

相關問題