LINQ到Sharepoint单个列表的多个内容类型
我使用SPMetal是为了为我的sharepoint网站生成实体类,但我不确定当一个列表有多个内容类型时,最佳做法是什么。例如,我有一个包含两种内容类型的任务列表,我通过SPMetal的配置文件来定义它们。这是我的定义LINQ到Sharepoint单个列表的多个内容类型,linq,sharepoint,Linq,Sharepoint,我使用SPMetal是为了为我的sharepoint网站生成实体类,但我不确定当一个列表有多个内容类型时,最佳做法是什么。例如,我有一个包含两种内容类型的任务列表,我通过SPMetal的配置文件来定义它们。这是我的定义 <List Member="Tasks" Name="Tasks"> <ContentType Class="LegalReview" Name="LegalReviewContent"/> <ContentType Cl
<List Member="Tasks" Name="Tasks">
<ContentType Class="LegalReview" Name="LegalReviewContent"/>
<ContentType Class="Approval" Name="ApprovalContent"/>
</List>
Linq2SharePoint将始终为列表中的所有ContentType返回第一个公共基本ContentType的对象。这不仅是因为必须使用某种描述的基类型来组合代码中的不同ContentType,而且它将只映射列表中所有ContentType上肯定存在的字段。但是,可以访问L2SP返回的底层SPListItem,从而确定ContentType并向下转换该项 作为从T4模板生成的自定义存储库层的一部分,我们对SPMetal生成的Item类进行了部分添加,该类实现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;
}
}
}
一旦您的L2SP实体上有了ContentType和基础SPListItem,就只需编写一个方法,该方法通过基类型的值和SPListItem中缺失字段的额外数据的组合返回派生ContentType实体的实例
更新:我实际上没有一个示例转换器类,因为我们没有以这种方式使用上面的项映射扩展。然而,我可以想象这样的事情会起作用:
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属性获取派生类型。这是我通常希望以一种或另一种形式生成的代码,因为它会非常重复,但这有点离题。Hi Rob感谢您的反馈,这是获取底层SPListItem的良好策略。我仍然不确定如何在给定列表项的情况下创建实体。。。是的,你可以这样做。由于创建对象时将初始化实体上的属性,因此不需要直接从SPListItem提取值的附加属性。关于实体没有附加到上下文,您是对的;我没有包括它,因为它取决于需求,但如果需要进行更新/删除,可以将实体附加到适当的上下文中。还有其他向下转换的方法,例如静态EntityConverter类或每个基类型上的方法。如果你需要一个例子,请告诉我,我会更新答案。嗨,Rob,如果你能发布entityconverter类的例子,我将不胜感激,如果它对你来说不是太多的工作。再次感谢您的帮助!
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;
}
}
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
}
}