使用CSOM操作SPO列表(强制签出)报错:文件被独占锁定
我开发了一款Word Add-In,功能是把Word文档导出成PDF后上传到SharePoint Online(SPO)列表,同时给新上传的PDF分配ContentType和SPO元数据。目标列表的配置如下:
- 启用主次版本控制
- 开启强制文件签出要求
导出和上传操作都能正常执行,但当Add-In尝试给文件分配新ContentType时,SPO抛出异常:file is locked for exclusive use by [当前执行Add-In的用户]。要是列表没开强制签出,这个功能就能正常运行。
现有代码
public void FileAssignContentType(string relativeFullName, string listTitle, string contentTypeName) { try { // connect to list Microsoft.SharePoint.Client.List list = this.web.GetListByUrl(listTitle); this.clientContext.Load(list); this.clientContext.ExecuteQuery(); // get content type ContentType newCT = list.GetContentTypeByName(contentTypeName); this.clientContext.Load(newCT, x => x.Id); this.clientContext.ExecuteQuery(); // assign content type to file Microsoft.SharePoint.Client.File file = this.getFile(relativeFullName); this.clientContext.ExecuteQuery(); ListItem item = list.GetItemByUniqueId(file.UniqueId); this.clientContext.Load(item); this.clientContext.ExecuteQuery(); item["ContentTypeId"] = newCT.Id; item.Update(); this.clientContext.ExecuteQuery(); // -> raises exception } catch (Exception ex) { throw new Exception(ex.Message); } }
原因分析
因为列表开启了强制签出,文件上传后会自动处于签出状态(当前用户就是签出者),此时直接修改ListItem会触发SPO的锁定检测,导致抛出“文件被独占锁定”的异常。
解决方案
在修改ContentType之前,先检查文件的签出状态,把文件签入后再进行更新操作。如果业务需要文件保持签出,更新完成后可以重新签出。
修改后的代码示例:
public void FileAssignContentType(string relativeFullName, string listTitle, string contentTypeName) { try { // 连接目标列表 Microsoft.SharePoint.Client.List list = this.web.GetListByUrl(listTitle); this.clientContext.Load(list); this.clientContext.ExecuteQuery(); // 获取要分配的ContentType ContentType newCT = list.GetContentTypeByName(contentTypeName); this.clientContext.Load(newCT, x => x.Id); this.clientContext.ExecuteQuery(); // 获取文件并加载签出状态、唯一ID Microsoft.SharePoint.Client.File file = this.getFile(relativeFullName); this.clientContext.Load(file, f => f.CheckOutType, f => f.UniqueId); this.clientContext.ExecuteQuery(); // 若文件处于签出状态,先签入 if (file.CheckOutType != CheckOutType.None) { // 按版本策略选择签入类型:MajorCheckIn生成主版本,MinorCheckIn生成次版本 file.CheckIn("签入以更新ContentType", CheckinType.MajorCheckIn); this.clientContext.ExecuteQuery(); } // 更新文件的ContentType ListItem item = list.GetItemByUniqueId(file.UniqueId); this.clientContext.Load(item); this.clientContext.ExecuteQuery(); item["ContentTypeId"] = newCT.Id; item.Update(); this.clientContext.ExecuteQuery(); // 可选:如果需要保持文件签出状态,更新后重新签出 // file.CheckOut(); // this.clientContext.ExecuteQuery(); } catch (Exception ex) { throw new Exception(ex.Message); } }
补充说明
- 签入类型
CheckinType的选择:如果列表启用主次版本,MajorCheckIn会生成1.0、2.0这类主版本,MinorCheckIn生成1.1、1.2这类次版本,根据你的业务需求选择即可。 - 确保操作的用户拥有签入/签出权限,以及修改列表项的权限。
内容的提问来源于stack exchange,提问作者Dgo
相关产品推荐
相关产品推荐

