Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
LINQ到Sharepoint单个列表的多个内容类型_Linq_Sharepoint - Fatal编程技术网

LINQ到Sharepoint单个列表的多个内容类型

LINQ到Sharepoint单个列表的多个内容类型,linq,sharepoint,Linq,Sharepoint,我使用SPMetal是为了为我的sharepoint网站生成实体类,但我不确定当一个列表有多个内容类型时,最佳做法是什么。例如,我有一个包含两种内容类型的任务列表,我通过SPMetal的配置文件来定义它们。这是我的定义 <List Member="Tasks" Name="Tasks"> <ContentType Class="LegalReview" Name="LegalReviewContent"/> <ContentType Cl

我使用SPMetal是为了为我的sharepoint网站生成实体类,但我不确定当一个列表有多个内容类型时,最佳做法是什么。例如,我有一个包含两种内容类型的任务列表,我通过SPMetal的配置文件来定义它们。这是我的定义

<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
        }
    }