0

管理コントローラー クラスがあり、管理タスクでは同じアクション メソッド呼び出しでエンティティを追加および削除する必要があるため、複数の管理者が同じアクション メソッドに同時にアクセスすると、いくつかの追加操作がから開始されるのではないかと心配しています。他の追加操作は 2 番目のトランザクションから開始されます。これにより、最終結果が矛盾する結果になる可能性があります。一部の追加および削除操作は TransactionOne から開始され、他の操作は transactionTwo から開始されるためです。たとえば、私はアクションメソッドを持っています:-

[Authorize]
 public class SecurityRoleController : Controller
            {

    Repository repository = new Repository();
    //code goes here
    [HttpPost]
    public ActionResult AssignPermisionLevel2(ICollection<SecurityroleTypePermision> list, int id)
        {
            repository.DeleteSecurityroleTypePermisions(id);
            foreach (var c in list)
            {
                repository.InsertOrUpdateSecurityroleTypePermisions(c,User.Identity.Name);
            }
            repository.Save();
            return RedirectToAction("AssignPermisionLevel", new { id = id });
        }

同じアクションメソッド呼び出しに対して追加および削除操作を実行する次のレパートリーメソッドを呼び出します:-

public void DeleteSecurityroleTypePermisions(int securityroleID)
{    
    var r = tms.SecurityroleTypePermisions.Where(a => a.SecurityRoleID == securityroleID);
    foreach (var c in r) {
        tms.SecurityroleTypePermisions.Remove(c);
    }

}

また、次のリポジトリ メソッド:-

public void InsertOrUpdateSecurityroleTypePermisions(SecurityroleTypePermision role, string username)
{    
     var auditinfo = IntiateAdminAudit(tms.AuditActions.SingleOrDefault(a => a.Name.ToUpper() == "ASSIGN PERMISION").ID, tms.SecurityTaskTypes.SingleOrDefault(a => a.Name.ToUpper() == "SECURITY ROLE").ID, username, tms.SecurityRoles.SingleOrDefault(a=>a.SecurityRoleID == role.SecurityRoleID).Name, tms.PermisionLevels.SingleOrDefault(a=>a.ID== role.PermisionLevelID).Name +  " --> " + tms.TechnologyTypes.SingleOrDefault(a=>a.AssetTypeID == role.AssetTypeID).Name);
     tms.SecurityroleTypePermisions.Add(role);
     InsertOrUpdateAdminAudit(auditinfo);
}

したがって、予期しない結果を避けるために、次のようにアクション メソッド内にロックを含めることにしました。

[Authorize]
    public class SecurityRoleController : Controller
    {

        Repository repository = new Repository();
public static object REQUEST_LOCK = new object();
//code goes here
[HttpPost]
        public ActionResult AssignPermisionLevel2(ICollection<SecurityroleTypePermision> list, int id)
        {
            lock (REQUEST_LOCK)
           {

                repository.DeleteSecurityroleTypePermisions(id);
                foreach (var c in list)
                {
                    repository.InsertOrUpdateSecurityroleTypePermisions(c, User.Identity.Name);
                }
                repository.Save();
                return RedirectToAction("AssignPermisionLevel", new { id = id });
           }
        }

だから、私がやっていることは正しい方法であり、私のアクションメソッド内に L​​ock があると、パフォーマンスに影響を与えたり、私が気付いていない欠点がありますか? よろしく

4

1 に答える 1

2

削除してから新しいレコードを挿入する理由をお伺いしてもよろしいですか? 既存のレコードを更新しないのはなぜですか? RDBMS は、更新の進行中に更新されるレコードをロックすることによってこれを自動的に処理するため、これにより、そもそもロックの必要性が回避されます (真のリレーショナル セマンティクスでは、更新は削除されてから、新しい値 - しかし、実際の RDBMS 実装がこれを具体的に行うとは思えませんが、データ操作に関して ATOMICity を保証する必要があります)。

いずれにせよ、非常に多数のユーザーがサイトに同時にアクセスすると予想される場合、これはパフォーマンスに影響を与える可能性があります (1 秒あたり数千のリクエストのオーダーで考えています — ここでは純粋な推測です)。基本的に、このアクション メソッドが呼び出された時点で、非同期マルチスレッド アプリケーションを同期シングルスレッド アプリケーションに変換します。

つまり、この設計によるパフォーマンスへの影響がある場合、ほぼ確実にこのアクション メソッドがボトルネックになります。

パフォーマンスへの影響を確実に知る唯一の方法は、Web サイトの負荷テストまたはストレス テストを実行することです。特に、このメソッドへの毎秒数千の (ほぼ) 同時リクエストに関してです。

更新:というメソッドがあるようInsertOrUpdateSecurityroleTypePermissionです。おそらく、このメソッド/ストアド プロシージャを、挿入するものと更新するものの 2 つに分ける必要があります。このようにして、前に述べたように、潜在的なスレッド化/ATOMICity の問題を完全に回避できます。

更新 2: OK、不必要な複雑さを引き起こしている設計上の決定を見つけたと思います。代わりに、トランザクションを使用してストアド プロシージャを設計し、所定の順序で必要なレコードの追加/削除を処理して、タスクを達成することができます。このようにして、DB を活用して、これがすべて ATOMICally に行われるようにします。また、トランザクションを使用すると、何かが無効であるか完了できない場合 (現在のコードでは実行できない) にずっと対処でき、アクション メソッド内のROLLBACKを取り除くことができます。lockさらに、引き続き EF を使用できます。EF を使用すると、DB で作成したストアド プロシージャを呼び出すことができます。同時ユーザーに関する限り、このアプローチを使用すると、「最後の書き込みが優先される」状況が引き続き発生します (たとえば、シーケンシャルな「

于 2013-08-21T13:12:19.587 に答える