LINQ-To-Sharepoint单个列表的多种内容类型 [英] LINQ-To-Sharepoint Multiple content types for a single list

查看:64
本文介绍了LINQ-To-Sharepoint单个列表的多种内容类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用SPMetal来为我的共享点网站生成实体类,并且我不确定在单个列表中有多种内容类型时,最佳实践是什么.例如,我有一个任务列表,其中包含2种内容类型,并且正在通过SPMetal的配置文件对其进行定义.这是我的定义...

I'm using SPMetal in order to generate entity classes for my sharepoint site and I'm not exactly sure what the best practice is to use when there are multiple content types for a single list. For instance I have a task list that contains 2 content types and I'm defining them via the config file for SPMetal. Here is my definition...

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

这似乎很好用,因为生成的对象确实继承自WorkflowTask,但是生成的数据上下文类型是WorkflowTask的列表.因此,当我执行查询时,我会得到一个WorkflowTask对象而不是LegalReview或Approval对象.如何使其返回正确类型的对象?

This seems to work pretty well in that the generated objects do inherit from WorkflowTask but the generated type for the data context is a List of WorkflowTask. So when I do a query I get back a WorkflowTask object instead of a LegalReview or Approval object. How do I make it return an object of the correct type?

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

更新 谢谢你回到我身旁.我不确定如何根据SPListItem重新创建类型,并希望得到反馈.

UPDATE Thanks for getting back to me. I'm not sure how I recreate the type based on the SPListItem and would appreciate any feedback.

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

推荐答案

Linq2SharePoint将始终为列表中的所有ContentType返回第一个公共基本ContentType的对象.这不仅是因为必须使用某种描述的基本类型来组合代码中的不同ContentType,而且还只会映射列表中所有ContentType上肯定存在的字段.但是,可以访问由L2SP返回的基础SPListItem,从而从中确定ContentType并向下转换该项目.

Linq2SharePoint will always return an object of the first common base ContentType for all the ContentTypes in the list. This is not only because a base type of some description must be used to combine the different ContentTypes in code but also it will then only map the fields that should definitely exist on all ContentTypes in the list. It is however possible to get access to the underlying SPListItem returned by L2SP and thus from that determine the ContentType and down cast the item.

作为从T4模板生成的自定义存储库层的一部分,我们对SPMetal生成的Item类进行了部分添加,该类实现了ICustomMapping以获取通常在L2SP实体上不可用的数据.下面是一个简化的版本,仅获取ContentType和ModifiedDate来显示方法.尽管我们使用的完整类也映射了修改者",创建日期/依据",附件",版本",路径"等,但所有对象的原理都是相同的.

As part of a custom repository layer that is generated from T4 templates we have a partial addition to the Item class generated by SPMetal which implements ICustomMapping to get the data not usually available on the L2SP entities. A simplified version is below which just gets the ContentType and ModifiedDate to show the methodology; though the full class we use also maps Modified By, Created Date/By, Attachments, Version, Path etc, the principle is the same for all.

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中缺少的字段.

Once you have the ContentType and the underlying SPListItem available on your L2SP entity it is simply a matter of writing a method which returns an instance of the derived ContentType entity from a combination of the values of the base type and the extra data for the missing fields from the SPListItem.

更新:我实际上没有示例转换器类,因为我们没有以这种方式使用上面对Item的映射扩展.但是我可以想象这样的事情会起作用:

UPDATE: I don't actually have an example converter class as we don't use the above mapping extension to Item in this way. However I could imagine something like this would work:

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的部分实例上放置一个方法以返回批准对象.

Or you could put a method on a partial instance of WorkflowTask to return an Approval object.

    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属性获取派生类型的调用方法.我通常希望以一种或另一种形式生成这种类型的代码,因为它会重复很多,但这有点不合时宜.

In either situation you would need to determine the method to call to get the derived type from the ContentTypeId property of the WorkflowTask. This is the sort of code I would normally want to generate in one form or another as it will be pretty repetitive but that is a bit off-topic.

这篇关于LINQ-To-Sharepoint单个列表的多种内容类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆