[SharePoint]リストにアイテムが約2100件以上あると・・・ の続きです。
「ドキュメント ライブラリ」の同じユーザが閲覧できるアイテムの数が1つのフォルダで約2100件超えている時にWeb画面で
<!-- #RENDER FAILED -->
と表示される件と、Microsoft.SharePoint名前空間のクラスを使用したプログラミングでの
System.Data.SqlClient.SqlException: 着信の表形式のデータ ストリーム (TDS) リモート プロシージャ コール (RPC) プロトコル ストリームが不適切です。この RPC 要求に指定されたパラメータが多すぎます。最大数は 2100 です。
という例外が起こる件についてです。kb958577(機械翻訳kb958577)
確実に再現できるC# コンソールアプリケーションのサンプルプログラムを作成してみました。MOSS2007 SP1(WSS3.0)のサーバーのローカルで実行します。
ファイルを大量にアップロードして、SPListItemCollection.Count プロパティを呼び出すだけです。
まずはSharePointサイトに新規にドキュメントライブラリを作成しておきます。
コンソールアプリケーションを作成して、参照設定でmicrosoft.sharepoint.dllを追加してcsファイル冒頭でusing Microsoft.SharePoint;を書いておきます。次のコードをプログラムの中に記述します。
/// <SUMMARY>
/// 同じファイルをコピーしてドキュメントライブラリに
/// </SUMMARY>
/// <PARAM name="docLib">ドキュメントライブラリ(SPDocumentLibraryオブジェクト)</PARAM>
/// <PARAM name="filePath">コピー元ファイルの絶対パス</PARAM>
/// <PARAM name="loginName">ドキュメント作成者、更新者とするユーザ</PARAM>
/// <PARAM name="start">連番開始番号</PARAM>
/// <PARAM name="end">連番終了番号</PARAM>
private static void UploadManyFiles(SPDocumentLibrary docLib, string filePath, string loginName, int start, int end)
{
SPWeb web = docLib.ParentWeb;
SPFileCollection filecoll = web.Folders[docLib.Title].Files;
string fileName = Path.GetFileNameWithoutExtension(filePath);
string fileExt = Path.GetExtension(filePath);
byte[] fileBytes = ReadAsBytes(filePath);
SPUser user = web.EnsureUser(loginName);
string url = "";
SPFile file = null;
for (int i = start; i <= end; i++)
{
url = string.Format("{0}/{1}{2:D4}{3}", filecoll.Folder.Url, fileName, i, fileExt);
Console.WriteLine("{0} is uploaded by {1}.", url, user.LoginName);
file = filecoll.Add(url, fileBytes, user, user, DateTime.Now, DateTime.Now);
file.Item.BreakRoleInheritance(false);
file.Item.SystemUpdate();
}
}
/// <SUMMARY>
/// ファイルをバイト列として読み込む
/// </SUMMARY>
/// <PARAM name="filePath">パス</PARAM>
/// <RETURNS>ファイルの中身のバイト列</RETURNS>
private static byte[] ReadAsBytes(string filePath)
{
MemoryStream ms = new MemoryStream();
byte[] buffer = new byte[1024];
using (BinaryReader br = new BinaryReader(new FileStream(filePath, FileMode.Open)))
{
while (br.Read(buffer, 0, buffer.Length) > 0)
{
ms.Write(buffer, 0, buffer.Length);
}
}
byte[] fileBytes = ms.ToArray();
return fileBytes;
}
Main()の中で以下の変数の宣言や代入して(省略)下のコードを書きます。
- docLib:そのSPDocumentLibraryオブジェクト。 SPListからasで取得するなど。
- filePath:適当なファイルの絶対パス。
- loginName:に投稿できる権限を持つユーザのログイン名。
・・・
//ドキュメント ライブラリのバージョン設定
//「このドキュメント ライブラリのファイルを編集するたびにバージョンを作成する 」で
//「 メジャーとマイナー (下書き) バージョンを作成する」を選択するのと同様。
docLib.EnableVersioning = true;
docLib.EnableMinorVersions = true;
// docLib.DraftVersionVisibility = DraftVisibilityType.Reader;//(※1)
docLib.Update();
Console.WriteLine("EnableVersioning = {0}", docLib.EnableVersioning);
Console.WriteLine("EnableMinorVersions = {0}", docLib.EnableMinorVersions);
Console.WriteLine("DraftVersionVisibility = {0}", docLib.DraftVersionVisibility);
UploadManyFiles(docLib,filePath, loginName, 0, 2110);
//「この ドキュメント ライブラリ の下書きアイテムを表示できるユーザー」を 「アイテムを編集できるユーザー」にするのと同じ
docLib.DraftVersionVisibility = DraftVisibilityType.Author;//(※2)
docLib.Update();//(※2)
Console.WriteLine("DraftVersionVisibility = {0}", docLib.DraftVersionVisibility);
Console.WriteLine("list.Items.Count = {0}", docLib.Items.Count);//←ここで上記の例外が発生します!!!
ちなみに、(※1)の行をコメント解除して、(※2)の行をコメント化すると例外は発生しません。
Webでの設定画面でも「ドキュメント ライブラリ」>「バージョン設定」 >「下書きアイテムのセキュリティ」>「この ドキュメント ライブラリ の下書きアイテムを表示できるユーザー」 のラジオボタンの選択によって、以下のように起きない場合もあります。
アイテムを閲覧できるすべてのユーザー |
この例外が発生しない。 |
アイテムを編集できるユーザー |
この例外が発生する。 |
アイテムの作成者およびアイテムを承認できるユーザー 「コンテンツの承認を必須にする」が「はい」のとき |
この例外が発生する。 |