SharePointでリスト(List)の疑似的ロック機構(Lock)を作成し連番生成(sequential number auto generator)する。(Silverlight, C#, List)

SharePointでは ユーザからList(リスト)のロック機構がありません。

(SQLでいうとテーブルロック、行ロック等のSQLで重要な機能が使えません)

Document Library(ドキュメントライブラリ) のChekOut/CheckIn(チェックアウト/チェックイン)はありますが、やりたいことは違います。

ここで困るのは、どうやって複数ユーザからくる連番を生成を矛盾なく生成(sequential number generator)するか問題になります。

世界中のサイト(MSや個人サイト)を検索しましたが、みんな困っているし、だれも解決していないのですが、原始的な方法がありますので。

その方法を説明します。

方法1:Webサービスで外部でロックできるDatabase Engineで生成する。(これは誰でもできそうなので省略します。)

方法2:SharePointに疑似的リストロック機構を作る。

まず以下で説明した。見積ヘッダー、見積明細でサンプルを説明します。

SharePointで伝票形式(ヘッダー、行)を複数(Multiple)のListで作るときの最適なキー(sequential number auto generator)の持ち方。(Silverlight, C#, List)

以下のような感じでロックリスト・連番リストを作成します。
見積ロックリスト

ID SEQNo
1 10001
2 10002

連番リスト

ID SEQNo SEQNoMain
1 1001 1

List_Quotation_Lock- Shmea.xml (見積ロックリスト)
18行目のように検索するときに重要な項目は以下のように設定してください。

  1. 必須:Required=”TRUE”
  2. ユニーク:EnforceUniqueValues=”TRUE”
  3. インデックス:Indexed=”TRUE”
<?xml version="1.0" encoding="utf-8"?>
<List xmlns:ows="Microsoft SharePoint" Title="List_Quotation_Lock" FolderCreation="FALSE" Direction="$Resources:Direction;" Url="Lists/List_Quotation_Lock" BaseType="0" xmlns="http://schemas.microsoft.com/sharepoint/">
  <MetaData>
    <ContentTypes>
      <ContentType ID="0x0100139d7d207b6f48fc889c801512ddd21f" Name="ListFieldsContentType">
        <FieldRefs>
          <FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title" />
          <FieldRef ID="{9da4e1bd-46a7-4756-8607-39dd18df2359}" Name="SEQNo" />
        </FieldRefs>
      </ContentType>
      <ContentTypeRef ID="0x01">
        <Folder TargetName="Item" />
      </ContentTypeRef>
      <ContentTypeRef ID="0x0120" />
    </ContentTypes>
    <Fields>
      <Field ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Type="Text" Name="Title" DisplayName="$Resources:core,Title;" Required="TRUE" SourceID="http://schemas.microsoft.com/sharepoint/v3" StaticName="Title" MaxLength="255" />
      <Field Name="SEQNo" ID="{9da4e1bd-46a7-4756-8607-39dd18df2359}" DisplayName="SEQNo" Type="Number" Required="TRUE" EnforceUniqueValues="TRUE" Indexed="TRUE"/>
    </Fields>
    <Views>
      <View BaseViewID="0" Type="HTML" MobileView="TRUE" TabularView="FALSE">
        <Toolbar Type="Standard" />
        <XslLink Default="TRUE">main.xsl</XslLink>
        <RowLimit Paged="TRUE">30</RowLimit>
        <ViewFields>
          <FieldRef Name="LinkTitleNoMenu"></FieldRef>
        </ViewFields>
        <Query>
          <OrderBy>
            <FieldRef Name="Modified" Ascending="FALSE"></FieldRef>
          </OrderBy>
        </Query>
        <ParameterBindings>
          <ParameterBinding Name="AddNewAnnouncement" Location="Resource(wss,addnewitem)" />
          <ParameterBinding Name="NoAnnouncements" Location="Resource(wss,noXinviewofY_LIST)" />
          <ParameterBinding Name="NoAnnouncementsHowTo" Location="Resource(wss,noXinviewofY_ONET_HOME)" />
        </ParameterBindings>
      </View>
      <View BaseViewID="1" Type="HTML" WebPartZoneID="Main" DisplayName="$Resources:core,objectiv_schema_mwsidcamlidC24;" DefaultView="TRUE" MobileView="TRUE" MobileDefaultView="TRUE" SetupPath="pages\viewpage.aspx" ImageUrl="/_layouts/images/generic.png" Url="AllItems.aspx">
        <Toolbar Type="Standard" />
        <XslLink Default="TRUE">main.xsl</XslLink>
        <RowLimit Paged="TRUE">30</RowLimit>
        <ViewFields>
          <FieldRef Name="ID" />
          <FieldRef Name="SEQNo" />
          <FieldRef Name="Attachments"></FieldRef>
          <FieldRef Name="LinkTitle"></FieldRef>
        </ViewFields>
        <Query>
          <OrderBy>
            <FieldRef Name="ID"></FieldRef>
          </OrderBy>
        </Query>
        <ParameterBindings>
          <ParameterBinding Name="NoAnnouncements" Location="Resource(wss,noXinviewofY_LIST)" />
          <ParameterBinding Name="NoAnnouncementsHowTo" Location="Resource(wss,noXinviewofY_DEFAULT)" />
        </ParameterBindings>
      </View>
    </Views>
    <Forms>
      <Form Type="DisplayForm" Url="DispForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
      <Form Type="EditForm" Url="EditForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
      <Form Type="NewForm" Url="NewForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
    </Forms>
  </MetaData>
</List>

List_SEQNo- Shmea.xml (連番リスト)
19,20行目のように検索するときに重要な項目は以下のように設定してください。

  1. 必須:Required=”TRUE”
  2. ユニーク:EnforceUniqueValues=”TRUE”
  3. インデックス:Indexed=”TRUE”
<?xml version="1.0" encoding="utf-8"?>
<List xmlns:ows="Microsoft SharePoint" Title="List_SEQNo" FolderCreation="FALSE" Direction="$Resources:Direction;" Url="Lists/List_SEQNo" BaseType="0" xmlns="http://schemas.microsoft.com/sharepoint/">
  <MetaData>
    <ContentTypes>
      <ContentType ID="0x0100b3669d5da61a455da30196fbe3b98886" Name="ListFieldsContentType">
        <FieldRefs>
          <FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title" />
          <FieldRef ID="{3e4dcade-a0d7-48b3-b0cb-5a5cd8e49cf9}" Name="SEQNo" />
          <FieldRef ID="{40cb335d-fcab-49eb-90d3-039c30f97649}" Name="SEQNoMain" />
        </FieldRefs>
      </ContentType>
      <ContentTypeRef ID="0x01">
        <Folder TargetName="Item" />
      </ContentTypeRef>
      <ContentTypeRef ID="0x0120" />
    </ContentTypes>
    <Fields>
      <Field ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Type="Text" Name="Title" DisplayName="$Resources:core,Title;" Required="TRUE" SourceID="http://schemas.microsoft.com/sharepoint/v3" StaticName="Title" MaxLength="255" />
      <Field Name="SEQNo" ID="{3e4dcade-a0d7-48b3-b0cb-5a5cd8e49cf9}" DisplayName="SEQNo" Type="Number" Required="TRUE" EnforceUniqueValues="TRUE" Indexed="TRUE" />
      <Field Name="SEQNoMain" ID="{40cb335d-fcab-49eb-90d3-039c30f97649}" DisplayName="SEQNoMain" Type="Number" Required="TRUE"/>
    </Fields>
    <Views>
      <View BaseViewID="0" Type="HTML" MobileView="TRUE" TabularView="FALSE">
        <Toolbar Type="Standard" />
        <XslLink Default="TRUE">main.xsl</XslLink>
        <RowLimit Paged="TRUE">30</RowLimit>
        <ViewFields>
          <FieldRef Name="LinkTitleNoMenu"></FieldRef>
        </ViewFields>
        <Query>
          <OrderBy>
            <FieldRef Name="Modified" Ascending="FALSE"></FieldRef>
          </OrderBy>
        </Query>
        <ParameterBindings>
          <ParameterBinding Name="AddNewAnnouncement" Location="Resource(wss,addnewitem)" />
          <ParameterBinding Name="NoAnnouncements" Location="Resource(wss,noXinviewofY_LIST)" />
          <ParameterBinding Name="NoAnnouncementsHowTo" Location="Resource(wss,noXinviewofY_ONET_HOME)" />
        </ParameterBindings>
      </View>
      <View BaseViewID="1" Type="HTML" WebPartZoneID="Main" DisplayName="$Resources:core,objectiv_schema_mwsidcamlidC24;" DefaultView="TRUE" MobileView="TRUE" MobileDefaultView="TRUE" SetupPath="pages\viewpage.aspx" ImageUrl="/_layouts/images/generic.png" Url="AllItems.aspx">
        <Toolbar Type="Standard" />
        <XslLink Default="TRUE">main.xsl</XslLink>
        <RowLimit Paged="TRUE">30</RowLimit>
        <ViewFields>
          <FieldRef Name="ID" />
          <FieldRef Name="SEQNo" />
          <FieldRef Name="SEQNoMain" />
          <FieldRef Name="LinkTitle" />
        </ViewFields>
        <Query>
          <OrderBy>
            <FieldRef Name="ID"></FieldRef>
          </OrderBy>
        </Query>
        <ParameterBindings>
          <ParameterBinding Name="NoAnnouncements" Location="Resource(wss,noXinviewofY_LIST)" />
          <ParameterBinding Name="NoAnnouncementsHowTo" Location="Resource(wss,noXinviewofY_DEFAULT)" />
        </ParameterBindings>
      </View>
    </Views>
    <Forms>
      <Form Type="DisplayForm" Url="DispForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
      <Form Type="EditForm" Url="EditForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
      <Form Type="NewForm" Url="NewForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
    </Forms>
  </MetaData>
</List>

プログラムにて連番をとります。

仕組み:

  1. 連番を取得するときに、1度[List_Quotation_Lock]にレコードを追加しておきます。そのときに追加するレコードはユニークが設定されているSEQNoには必ず同一キーを設定(今回は”0″)することにより、疑似的排他ロックをします。
  2. この時点でほかのユーザが連番を取得しようと、[List_Quotation_Lock]にレコードを追加しても、ユニークキーエラーになります。エラー時にはユーザに「しばらくまってから実行してください」と表示します。(プログラムで数回リトライするか、キュー等を使って処理すればもっといいかも。)
  3. 疑似的ロックができたので、[List_SEQNo]から連番を取得して、連番に[+1]して更新します。
  4. 連番を取り終わったら、[List_Quotation_Lock]からロックレコードを削除しておきます。

サンプルプログラム:
267~346が連番をとるプログラムです。

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using SP = Microsoft.SharePoint.Client;
//using System.Collections.ObjectModel;
using System.Collections.ObjectModel;

using System.ComponentModel;

namespace SilverlightProjectMain.Models.SharepointClient.Base
{
    //デリゲート
    public delegate void Adapter_EventHandler(bool IsSuccess, Exception e);
    public delegate void Adapter_EventHandler<Type>(bool IsSuccess, Exception e, Type typeData);
    public delegate void Adapter_EventHandlerListItemCollection(bool IsSuccess, Exception e, SearchType searchType, SP.ListItemCollection listItemsMain, SP.ListItemCollection listItemsSub);
    public delegate void Adapter_EventHandlerCollection<Type>(bool IsSuccess, Exception e, System.Collections.ObjectModel.ObservableCollection<Type> observableCollection);
    public delegate void Adapter_EventHandlerCollection<Type1, Type2>(bool IsSuccess, Exception e, System.Collections.ObjectModel.ObservableCollection<Type1> observableCollection1, System.Collections.ObjectModel.ObservableCollection<Type2> observableCollection2);

    public class CData : INotifyPropertyChanged

    {
        public int ID { get; set; }
        public int SEQNo { get; set; }

        #region INotifyPropertyChanged メンバ
        /// <summary>
        /// プロパティ変更時のイベント
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, e);
        }

        protected virtual void OnPropertyChanged(string name)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
        #endregion

    }

    public enum SearchType
    {
        SEQNo,
        All,
        Type001,
        Type002,
        Type003,
        Type004,
        Type005
    }

    public class Adapter_Base_List
    {
        private const int DEFAULT_ROWLIMIT = 30;

        protected string _strListMain = string.Empty;
        protected string _strListSub = string.Empty;
        protected string _strListDoc = string.Empty;
        protected int _nListSEQNo_SEQNo = int.MinValue;
        protected string _strListLock = string.Empty;

        //Sample 動作OKのCAML
        //var camlQuery = new SP.CamlQuery();
        //camlQuery.ViewXml = "<View><Query><Where><Eq><FieldRef Name='ID' /><Value Type='Integer'>1</Value></Eq></Where></Query></View>";
        //camlQuery.ViewXml = "<View><Query><Where><Eq><FieldRef Name='CustomerName' /><Value Type='Text'>111</Value></Eq></Where></Query></View>";
        //camlQuery.ViewXml = "<View><Query><Where><Contains><FieldRef Name='CustomerName' /><Value Type='Text'>111</Value></Contains></Where></Query></View>";

        //その他キーワード(StartWith, In)

        //listItems = list.GetItems(camlQuery);
        //clientContext.Load(listItems);

        static protected SP.ListItemCollection GetItemsFromCAMLQuery(SP.List list)
        {
            return GetItemsFromCAMLQuery(list, "", "", DEFAULT_ROWLIMIT);
        }
        static protected SP.ListItemCollection GetItemsFromCAMLQuery(SP.List list, string strWhere)
        {
            return GetItemsFromCAMLQuery(list, strWhere, "", DEFAULT_ROWLIMIT);
        }

        static protected SP.ListItemCollection GetItemsFromCAMLQuery(SP.List list, string strWhere, string strOrderBy)
        {
            return GetItemsFromCAMLQuery(list, strWhere, strOrderBy, DEFAULT_ROWLIMIT);
        }

        static protected SP.ListItemCollection GetItemsFromCAMLQuery(SP.List list, string strWhere, string strOrderBy, int nRowLimit)
        {
            var camlQuery = new SP.CamlQuery();

            string strTemp = "<View>";
            strTemp += "<Query>" + strWhere + "</Query> ";
            strTemp += "<RowLimit>" + nRowLimit.ToString() + "</RowLimit>";
            strTemp += strOrderBy;
            strTemp += "</View>";

            camlQuery.ViewXml  = strTemp;
            return list.GetItems(camlQuery);
        }

        static protected string GetWhere_SEQNo(int nSEQNo)
        {
            return "<Where><Eq><FieldRef Name='SEQNo' /><Value Type='Integer'>" + nSEQNo.ToString() + "</Value></Eq></Where>";
        }

        static protected string GetWhere_PersonSEQNo(int nSEQNo)
        {
            return "<Where><Eq><FieldRef Name='PersonSEQNo' /><Value Type='Integer'>" + nSEQNo.ToString() + "</Value></Eq></Where>";
        }

        static protected string GetOrderby_ID()
        {
            return "<OrderBy><FieldRef Name='ID'></FieldRef></OrderBy>";
        }

        static protected string GetWhere_FileLeafRef(string strDocumentName)
        {
            return "<Where><Eq><FieldRef Name='FileLeafRef' /><Value Type='Text'>" + strDocumentName + "</Value></Eq></Where>";
        }

        static protected void DeleteAllItems(SP.List list, SP.ListItemCollection  listItems)
        {
            foreach (var li in listItems)
            {
                SP.ListItem item = list.GetItemById(li.Id);
                item.DeleteObject();
            }
        }

        ////////////////////////////////////////////////////////////////////////////
        ///  検索処理
        ////////////////////////////////////////////////////////////////////////////
        protected void AsyncDownload_Sub(Adapter_EventHandlerListItemCollection adapter_EventHandler, SearchType searchType, int nSEQNo, string strCustomerName)
        {
            using (var clientContext = new SP.ClientContext(SP.ApplicationContext.Current.Url))
            {
                SP.List listMain = null;
                SP.List listSub = null;

                SP.ListItemCollection listItemsMain = null;
                SP.ListItemCollection listItemsSub = null;

                string strWhere = string.Empty;
                string strOrderBy = string.Empty;

                listMain = clientContext.Web.Lists.GetByTitle(_strListMain);

                if (!string.IsNullOrEmpty(_strListSub))
                {
                    listSub = clientContext.Web.Lists.GetByTitle(_strListSub);
                }

                switch (searchType)
                {
                    //nSEQNoで検索(SPList.GetItemById)
                    case SearchType.SEQNo:
                        strWhere = GetWhere_SEQNo(nSEQNo);
                        listItemsMain = GetItemsFromCAMLQuery(listMain, strWhere);

                         //明細行取得
                        if (!string.IsNullOrEmpty(_strListSub))
                        {
                            strWhere = GetWhere_PersonSEQNo(nSEQNo);
                            strOrderBy = "<OrderBy><FieldRef Name=\"No\"></FieldRef></OrderBy>";
                            listItemsSub = GetItemsFromCAMLQuery(listSub, strWhere, strOrderBy);
                            clientContext.Load(listItemsSub);
                        }
                        break;

                    //全件検索(SP.CamlQuery)
                    case SearchType.All:
                        listItemsMain = GetItemsFromCAMLQuery(listMain);
                        break;

                    //検索キーワードを含む(SP.CamlQuery)
                    case SearchType.Type001:
                        //完全一致;    column =‘SearchWord’
                        //listItems = GetItemsFromCAMLQuery(list, "<Where><Eq><FieldRef Name='CustomerName' /><Value Type='Text'>" + strCustomerName + "</Value></Eq></Where>");

                        //検索キーワードを含む: column like ‘%SearchWord%’
                        strWhere = "<Where><Contains><FieldRef Name='CustomerName' /><Value Type='Text'>" + strCustomerName + "</Value></Contains></Where>";
                        listItemsMain = GetItemsFromCAMLQuery(listMain, strWhere);
                        break;
                    default:
                        throw new Exception("存在しないSearchTypeです。SearchType=" + searchType.ToString());
                        break;
                }

                //全件検索(SP.CamlQuery)
                //検索キーワードを含む(SP.CamlQuery)
                clientContext.Load(listItemsMain); //必用?

                clientContext.ExecuteQueryAsync(
                    new SP.ClientRequestSucceededEventHandler(delegate(object o, SP.ClientRequestSucceededEventArgs successargs)
                    {
                        adapter_EventHandler(true, null,searchType, listItemsMain, listItemsSub);
                    }),
                    new SP.ClientRequestFailedEventHandler(delegate(object o, SP.ClientRequestFailedEventArgs failedArgs)
                    {
                        adapter_EventHandler(false, new Exception(failedArgs.ErrorDetails + "   " + failedArgs.Message), searchType, null, null);
                    })
                );
            }
        }

        ////////////////////////////////////////////////////////////////////////////
        ///  新規追加 or 更新処理
        ////////////////////////////////////////////////////////////////////////////
        private Adapter_EventHandler<int> _AsyncUpload_Sub_adapter_EventHandler = null;
        private bool _AsyncUpload_Sub_IsAddNew;

        protected enum SEQType
        {
            Quotation
        }

        protected void AsyncUpload_Sub(Adapter_EventHandler<int> adapter_EventHandler, bool IsAddNew, int nSEQNo)
        {
            _AsyncUpload_Sub_adapter_EventHandler = adapter_EventHandler;
            _AsyncUpload_Sub_IsAddNew = IsAddNew;

            if (IsAddNew)
            {
                AsyncUpload_Sub_AddNew(adapter_EventHandler);
            }
            else
            {
                AsyncUpload_Sub_Update(nSEQNo);
            }
        }

        private const  int LIST_LOCKTABLE_SEQNO = 0;
        private const int LIST_SEQNO_START_SEQNO = 1;

        private void AsyncUpload_Sub_AddNew(Adapter_EventHandler<int> adapter_EventHandler)
        {
            using (var clientContext = new SP.ClientContext(SP.ApplicationContext.Current.Url))
            {
                SP.List listSEQNo = null;
                SP.List listLock = null;

                SP.ListItemCollection listItemsSEQNo = null;
                SP.ListItemCollection listItemsLock = null;

                string strWhere = string.Empty;
                string strOrderBy = string.Empty;

                string strListSEQNo = "List_SEQNo";
                string strListLock = _strListLock;

                listSEQNo = clientContext.Web.Lists.GetByTitle(strListSEQNo);
                listLock = clientContext.Web.Lists.GetByTitle(strListLock);

                //疑似行ロックする。
                {
                    SP.ListItem li = null;
                    li = listLock.AddItem(new SP.ListItemCreationInformation());
                    //行更新
                    li["SEQNo"] = LIST_LOCKTABLE_SEQNO;
                    li.Update();
                }

                clientContext.ExecuteQueryAsync(
                    new SP.ClientRequestSucceededEventHandler(delegate(object o, SP.ClientRequestSucceededEventArgs successargs)
                    {
                        //SEQNoを取得する。
                        strWhere = GetWhere_SEQNo(_nListSEQNo_SEQNo);
                        listItemsSEQNo = GetItemsFromCAMLQuery(listSEQNo, strWhere);
                        clientContext.Load(listItemsSEQNo);

                        //ロックテーブルを取得する。
                        strWhere = GetWhere_SEQNo(LIST_LOCKTABLE_SEQNO);
                        listItemsLock = GetItemsFromCAMLQuery(listLock, strWhere);
                        clientContext.Load(listItemsLock);

                        clientContext.ExecuteQueryAsync(
                            new SP.ClientRequestSucceededEventHandler(delegate(object o2, SP.ClientRequestSucceededEventArgs successargs2)
                            {
                                int SEQNo;
                                if(listItemsSEQNo.Count ==0)
                                {
                                    {
                                        SP.ListItem li = null;
                                        li = listSEQNo.AddItem(new SP.ListItemCreationInformation());
                                        //行更新
                                        li["SEQNo"] = _nListSEQNo_SEQNo;
                                        SEQNo = LIST_SEQNO_START_SEQNO;
                                        li["SEQNoMain"] = SEQNo;
                                        li.Update();
                                    }
                                }
                                else
                                {
                                    //SEQNoに +1する。
                                    SEQNo = Static_Common.ListItemToInt(listItemsSEQNo[0]["SEQNoMain"]);
                                    SEQNo++;
                                    listItemsSEQNo[0]["SEQNoMain"] = SEQNo;
                                    listItemsSEQNo[0].Update();
                                }

                                //ロックテーブル削除する。
                                DeleteAllItems(listLock, listItemsLock);

                                clientContext.ExecuteQueryAsync(
                                    new SP.ClientRequestSucceededEventHandler(delegate(object o3, SP.ClientRequestSucceededEventArgs successargs3)
                                    {
                                        //SEQNo作成成功
                                        AsyncUpload_Sub_Update(SEQNo);
                                    }),
                                    new SP.ClientRequestFailedEventHandler(delegate(object o3, SP.ClientRequestFailedEventArgs failedArgs3)
                                    {
                                        adapter_EventHandler(false, new Exception(failedArgs3.ErrorDetails + "   " + failedArgs3.Message), int.MinValue);
                                    })
                                );
                            }),
                            new SP.ClientRequestFailedEventHandler(delegate(object o2, SP.ClientRequestFailedEventArgs failedArgs2)
                            {
                                adapter_EventHandler(false, new Exception(failedArgs2.ErrorDetails + "   " + failedArgs2.Message), int.MinValue);
                            })
                        );

                    }),
                    new SP.ClientRequestFailedEventHandler(delegate(object o, SP.ClientRequestFailedEventArgs failedArgs)
                    {

                        //ロックできなかった。

                        //今後の改善ポイント
                        // ロックテーブルが5分以上ふるかったらありえないので強制的に削除する。
                        // その後リトライする。

                        //とりあえず今はユーザにメッセージを返すだけにする。
                        adapter_EventHandler(false, new Exception("連番作成時(SEQNo)に行ロック(疑似)できませんでした。しばらくして再度実行してください。"), int.MinValue);

                    })
                );

            }
        }

        private void AsyncUpload_Sub_Update(int nSEQNo)
        {
            AsyncUpload_Sub_Sub(_AsyncUpload_Sub_adapter_EventHandler, _AsyncUpload_Sub_IsAddNew, nSEQNo);
        }
        private void AsyncUpload_Sub_Sub(Adapter_EventHandler<int> adapter_EventHandler, bool IsAddNew, int nSEQNo)
        {
            using (var clientContext = new SP.ClientContext(SP.ApplicationContext.Current.Url))
            {
                SP.List listMain = null;
                SP.List listSub = null;

                SP.ListItemCollection listItemsMain = null;
                SP.ListItemCollection listItemsSub = null;

                string strWhere = string.Empty;
                string strOrderBy = string.Empty;

                listMain = clientContext.Web.Lists.GetByTitle(_strListMain);

                if (!string.IsNullOrEmpty(_strListSub))
                {
                    listSub = clientContext.Web.Lists.GetByTitle(_strListSub);
                }

                //新規or更新
                {
                    if (IsAddNew)
                    {
                    }
                    else
                    {
                        //取得
                        {
                            strWhere = GetWhere_SEQNo(nSEQNo);
                            listItemsMain = GetItemsFromCAMLQuery(listMain, strWhere);
                            clientContext.Load(listItemsMain); //IDを取るのに必要?
                        }

                        //明細行取得
                        if (!string.IsNullOrEmpty(_strListSub))
                        {
                            strWhere = GetWhere_PersonSEQNo(nSEQNo);
                            listItemsSub = GetItemsFromCAMLQuery(listSub, strWhere);
                            clientContext.Load(listItemsSub); //明細をとるのに必要?
                        }
                    }
                }

                clientContext.ExecuteQueryAsync(
                    new SP.ClientRequestSucceededEventHandler(delegate(object o, SP.ClientRequestSucceededEventArgs successargs)
                    {
                        AsyncUpload_Sub_OnSetValue(nSEQNo, IsAddNew, listMain, listSub, listItemsMain, listItemsSub);

                        clientContext.ExecuteQueryAsync(
                                new SP.ClientRequestSucceededEventHandler(delegate(object o3, SP.ClientRequestSucceededEventArgs successargs3)
                                {
                                    adapter_EventHandler(true, null, nSEQNo);

                                }),
                                new SP.ClientRequestFailedEventHandler(delegate(object o3, SP.ClientRequestFailedEventArgs failedArgs)
                                {
                                    adapter_EventHandler(false, new Exception(failedArgs.ErrorDetails + "   " + failedArgs.Message), nSEQNo);
                                }));
                    }),
                    new SP.ClientRequestFailedEventHandler(delegate(object o, SP.ClientRequestFailedEventArgs failedArgs)
                    {
                        adapter_EventHandler(false, new Exception(failedArgs.ErrorDetails + "   " + failedArgs.Message), 0);
                    }));
            }
        }

        protected virtual void AsyncUpload_Sub_OnSetValue(int nSEQNo, bool IsAddNew, SP.List listMain, SP.List listSub, SP.ListItemCollection listItemsMain , SP.ListItemCollection listItemsSub)
        {
        }

        ////////////////////////////////////////////////////////////////////////////
        ///  削除処理
        ////////////////////////////////////////////////////////////////////////////
        protected void AsyncDelete(Adapter_EventHandler adapter_EventHandler, int nSEQNo, string strListDocName)
        {
            using (var clientContext = new SP.ClientContext(SP.ApplicationContext.Current.Url))
            {
                SP.List listMain = null;
                SP.List listSub = null;

                SP.ListItemCollection listItemsMain = null;
                SP.ListItemCollection listItemsSub = null;

                string strWhere = string.Empty;
                string strOrderBy = string.Empty;

                listMain = clientContext.Web.Lists.GetByTitle(_strListMain);
                listItemsMain = null;
                //削除処理
                strWhere = GetWhere_SEQNo(nSEQNo);
                listItemsMain = GetItemsFromCAMLQuery(listMain, strWhere);
                clientContext.Load(listItemsMain); //明細をとるのに必要?

                //明細行取得
                if (!string.IsNullOrEmpty(_strListSub))
                {
                    listSub = clientContext.Web.Lists.GetByTitle(_strListSub);
                    listItemsSub = null;
                    strWhere = GetWhere_PersonSEQNo(nSEQNo);
                    listItemsSub = GetItemsFromCAMLQuery(listSub, strWhere);
                    clientContext.Load(listItemsSub); //明細をとるのに必要?
                }

                clientContext.ExecuteQueryAsync(
                    new SP.ClientRequestSucceededEventHandler(delegate(object o, SP.ClientRequestSucceededEventArgs successargs)
                    {
                        try
                        {
                            //削除
                            if (null != listMain)
                            {
                                DeleteAllItems(listMain, listItemsMain);
                            }

                            //明細行削除
                            if (null != listSub)
                            {
                                DeleteAllItems(listSub, listItemsSub);
                            }

                            clientContext.ExecuteQueryAsync(
                                    new SP.ClientRequestSucceededEventHandler(delegate(object o3, SP.ClientRequestSucceededEventArgs successargs3)
                                    {
                                        try
                                        {
                                            if (string.IsNullOrEmpty(_strListMain))
                                            {
                                                adapter_EventHandler(true, null);
                                            }
                                            else
                                            {
                                                Adapter_Base_DocumentLibrary.AsyncDelete(
                                                    new Adapter_EventHandler<int>(delegate(bool IsSuccess, Exception e2, int nCount)
                                                    {
                                                        adapter_EventHandler(IsSuccess, e2);

                                                    }),
                                                    _strListDoc,
                                                    strListDocName
                                                    );
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            adapter_EventHandler(false, ex);
                                        }
                                    }),
                                    new SP.ClientRequestFailedEventHandler(delegate(object o3, SP.ClientRequestFailedEventArgs failedArgs)
                                    {
                                        adapter_EventHandler(false, new Exception(failedArgs.ErrorDetails + "   " + failedArgs.Message));
                                    }));
                        }
                        catch (Exception ex2)
                        {
                            adapter_EventHandler(false, ex2);
                        }

                    }),
                    new SP.ClientRequestFailedEventHandler(delegate(object o, SP.ClientRequestFailedEventArgs failedArgs)
                    {
                        adapter_EventHandler(false, new Exception(failedArgs.ErrorDetails + "   " + failedArgs.Message));
                    })
                );
            }
        }
    }

}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です