我正在使用SPMetal为我的sharepoint网站生成实体类,而且我不确定当单个列表有多种内容类型时,最佳做法是什么。例如,我有一个包含2种内容类型的任务列表,我通过SPMetal的配置文件定义它们。这是我的定义......
<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};
}
答案 0 :(得分:2)
Linq2SharePoint将始终为列表中的所有ContentTypes返回第一个公共基础ContentType的对象。这不仅是因为必须使用某些描述的基本类型来组合代码中的不同ContentType,而且它还将仅映射应该在列表中的所有ContentType上明确存在的字段。但是,可以访问L2SP返回的基础SPListItem,从而确定ContentType并向下投射项目。
作为从T4模板生成的自定义存储库层的一部分,我们对SPMetal生成的Item类进行了部分添加,该类实现了ICustomMapping以获取L2SP实体上通常不可用的数据。下面是一个简化版本,它只是获取ContentType和ModifiedDate来显示方法;虽然我们使用的完整类也映射了Modified By,Created Date / By,Attachments,Version,Path等,但原则对所有人来说都是一样的。
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,就可以编写一个方法,该方法从基类型和额外数据的值的组合中返回派生的ContentType实体的实例。 SPListItem中缺少的字段。
更新:我实际上没有示例转换器类,因为我们没有以这种方式使用上面的Item映射扩展。但是我可以想象这样的事情会起作用:
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的部分实例上放置一个方法来返回Approval对象。
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属性中获取派生类型。这是我通常想要以一种或另一种形式生成的代码,因为它会非常重复,但这有点偏离主题。