在SharePoint中使用WorkItem方式批量处理Item

我们知道SharePoint使用timer job来定时处理一些任务,只需要继承SPJobDefinition类,然后重写Execute方法,就可以创建出自己的timer job了。我们经常使用timer job来处理列表中的item,例如定时更新item的状态等等,这样的操作一般来讲是在Execute方法中获取需要处理的item,然后遍历这些item来执行一些操作。如果我们需要一些更大的灵活性来处理item,比如按照需要动态的添加需要处理的item,指定处理item的时间,或者动态移除一些不再需要处理的item,可以使用SharePoint提供的另一种专门为了批量处理item而设计的timer job:work item timer job (SPWorkItemJobDefinition)。这种方式允许你以队列的的方式批量处理item,而且是异步处理。这种方式相对于常用的timer job,处理item更加灵活方便,可以根据需要将待处理的item添加到队列中或者从队列中移除,指定下次运行时间等等。

首先介绍一下如何创建一个Work Item Timer Job,其实很简单,与创建SPJobDefinition类似,在project中添加一个类WorkItemJob,继承SPWorkItemJobDefinition,然后需要重写一些方法和属性:

public class WorkItemJob : SPWorkItemJobDefinition
    {
        public static readonly string WorkItemJobDisplayName = "WorkItemJob Demo";
        public static readonly Guid WorkItemTypeId = new Guid("{B5597728-498B-4123-9C0E-DA6640CE0BC9}");

        public override string DisplayName
        {
            get
            {
                return WorkItemJobDisplayName;
            }
        }

        public override Guid WorkItemType()
        {
            return WorkItemTypeId;
        }

        public override int BatchFetchLimit
        {
            get
            {
                return 50;
            }
        }

        #region 构造函数
        public WorkItemJob() { }
        public WorkItemJob(string name, SPWebApplication webApplicaiton) : base(name, webApplicaiton) { }
        #endregion

        protected override bool ProcessWorkItem(SPContentDatabase contentDatabase, SPWorkItemCollection workItems, SPWorkItem workItem, SPJobState jobState)
        {
            
        }
    }
其中DisplayName是timer job的名字,WorkItemType方法返回的是timer job的唯一标识,这个在之后的AddWorkItem方法中需要使用,BatchFetchLimit是一次timer job运行处理的work item的数量。我们需要重写的是ProcessWorkItem方法来实现自己的逻辑。

有了work item timer job之后,就可以使用SPSite.AddWorkItem这个方法将需要处理的item添加到队列中,这个方法需要的参数比较多,以下代码是使用一个控制台程序,将Tasks列表中的一个item添加到队列中:

class Program
    {
        static void Main(string[] args)
        {
            SPSecurity.RunWithElevatedPrivileges(() =>
            {
                using (SPSite site = new SPSite("http://sp2013test"))
                {
                    using (SPWeb web = site.OpenWeb())
                    {
                        SPList list = web.Lists["Tasks"];
                        SPListItem item = list.GetItemById(1);
                        SPUser user = web.SiteUsers[@"demo\administrator"];
                        Guid workItemId = Guid.NewGuid();
                        site.AddWorkItem(
                            workItemId,
                            DateTime.Now.ToUniversalTime(),  //指定运行时间,这里需要指定UTC时间
                            new Guid("{B5597728-498B-4123-9C0E-DA6640CE0BC9}"), //Work item timer job中定义的WorkItemTypeId
                            web.ID,
                            list.ID,
                            item.ID,
                            true,
                            item.UniqueId,
                            item.UniqueId,
                            user.ID,
                            null,
                            "Text you can use in timer job",
                            Guid.Empty);
                    }
                }
            });
        }
    }

其中各个参数的具体解释可以参考微软文档,需要注意的是,执行AddWorkItem方法需要提升权限到Site Collection Administrator。执行以上代码我们就添加了一个work item,这个work item将会在指定的时间执行,因为现在我们的ProcessWorkItem方法是空的,所以timer job什么都不做。我们加上一些逻辑来更新一个item的title:

protected override bool ProcessWorkItem(SPContentDatabase contentDatabase, SPWorkItemCollection workItems, SPWorkItem workItem, SPJobState jobState)
        {
            if (workItem != null)
            {
                using (SPSite site = new SPSite(workItem.SiteId))
                {
                    using (SPWeb web = site.OpenWeb(workItem.WebId))
                    {
                        try
                        {
                            SPList list = web.Lists[workItem.ParentId]; //获取list
                            SPListItem item = list.GetItemByUniqueId(workItem.ItemGuid); //获取待处理的item
                            string data = workItem.TextPayload;  //获取AddWorkItem方法“strTextPayload”参数传入的字符串数据
                            string newTitle = string.Format("{0} - {1}", data, DateTime.Now.ToLongTimeString()); 
                            item["Title"] = newTitle;  //更新item的title
                            item.Update();
                            //使用UpdateWorkItem的方法,指定下次运行的时间,需要使用UTC时间,这里指定4分钟之后再次运行
                            workItems.UpdateWorkItem(workItem.Id, DateTime.Now.AddMinutes(4).ToUniversalTime(), null, "run again");
                        }
                        catch (Exception)
                        {
                            throw;
                        }
                        finally
                        {
                            //以下注释的代码用来删除workitem,即将其从队列中移除
                            //workItems.SubCollection(site, web, 0, (uint)workItems.Count).DeleteWorkItem(workItem.Id);
                        }
                        
                    }
                }
            }

           return true;
        }

需要注意两个地方,一个是在使用AddWorkItem方法添加workitem的时候是可以传递数据给ProcessWorkItem方法的,使用“ strTextPayload”这个参数指定需要传入的字符串。

另外一个是在如果想再次处理这个work item,需要使用UpdateWorkItem方法指定下次运行时间,同时也可以指定TextPayload,如果不需要处理这个work item,可以使用DeleteWorkItem方法将其从队列中删除,具体参见finally代码块。

运行之后,item的title会根据指定的时间而更新,将最新的时间显示在title上:

第一次运行:


第二次运行:



第三次运行:


可以看到,采用work item timer job的方式,不仅可以批量处理item,可以指定下次的运行时间,在处理item的时候很灵活方便。

以下是一些可能使用workitem方式的场景

1. 一些耗时的操作,有的时候用户每创建一个item,都要对应执行一些耗时的操作,比如创建一个相应的站点,访问AD,数据库或者其他资源等等。

2. 定时批量处理item。如果workitem没有从队列中移除,会一直处理下去。因此可以批量更新item的状态等等。

参考:点击打开链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值