2011-06-28 11 views
0

私は現在、この巨大で低速なコードを持っています。私はいつも実行するのに時間がかかります。私はそれをいくらか読みやすく、全体的により速い経験を提供するためにリファクタリングする過程にあります... 基本的に私は私のサーバテキストファイルには多くのデータが格納されています。このスクリプトはこのファイルから読み込み、EFを介して要素をデータベースに追加します。これには時間がかかります。私は私にこれを改善する方法についていくつかのアドバイスを与えてください非同期コントローラは実行可能なオプションですか?

...彼らはこのような場合のために意図されているかどうかわから非同期コントローラが、イムないという機能が存在しているはず

public class ScriptMetabolicoController : Controller 
     { 
      private IPortalAdministradorServices _servicioPortalAdministrador = new PortalAdministradorServices();    
IRepositorio<Historia> historiarepo = new Repositorio<Historia>(); 
       IRepositorio<Indicador_Metabolico> indicadorrepo = new Repositorio<Indicador_Metabolico>(); 

      [Authorize(Roles = "Administrador")] 
      public ActionResult Index() 
      { 


       DirectoryInfo myDir = new DirectoryInfo(Server.MapPath("labtelFTP")); 


       ViewData["sinActualizacionesPendientes"] = false; 
       if (myDir.GetFiles().Count() != 0) 
       { 
        try 
        { 
         foreach (FileInfo file in myDir.GetFiles()) 
         { 
          if (file.Extension != ".aspx") 
          { 
           StreamReader stream; 
           stream = file.OpenText(); 

           while (stream.Peek() != -1) 
           { 
            string linea = stream.ReadLine(); 
            string cedula = linea.Substring(2, 18).Trim(); 
            Historia historia; 
            if (historiarepo.ObtenerTodos().Where(h => h.Cedula == cedula).Count() == 1) 
            { 
             //Se obtiene la historia por la cédula del participante 
             historia = historiarepo.ObtenerTodos().Where(h => h.Cedula == cedula).First(); 

             //Se inicializan las fechas de solicitud y las fechas de reporte del examen que se lee del archivo 
             var numero = historia.Examenes_Metabolicos.Count(); 

             int anor = Convert.ToInt32(linea.Substring(216, 4)); 
             int mesr = Convert.ToInt32(linea.Substring(220, 2)); 
             int diar = Convert.ToInt32(linea.Substring(222, 2)); 
             DateTime fecha_reporte = new DateTime(anor, mesr, diar); 

             int anos = Convert.ToInt32(linea.Substring(202, 4)); 
             int mess = Convert.ToInt32(linea.Substring(206, 2)); 
             int dias = Convert.ToInt32(linea.Substring(208, 2)); 
             DateTime fecha_solicitud = new DateTime(anos, mess, dias); 

             //Variable que tendrá el examen en cuestión 
             Examen_Metabolico examen; 

             //Si es el primer indicador de un examen nuevo en la historia del participante se crea una instancia nueva 
             if (historia.Examenes_Metabolicos.Where(e => e.Fecha_Solicitud == fecha_solicitud).Count() == 0) 
             { 

              examen = new Examen_Metabolico(); 
              examen.Fecha_Reporte = fecha_reporte; 
              examen.Fecha_Solicitud = fecha_solicitud; 
              historia.Examenes_Metabolicos.Add(examen); 

              //Se crea en base de datos el examen vacío para luego agregarle valores metabólicos asociados a el. 
              //historiarepo.GuardarTodo(); 
             } 
             //Si el indicador no es el primero de un examen nuevo entonces se le asigna a la variable 'examen' la referencia del mismo 
             else 
             { 
              examen = historia.Examenes_Metabolicos.Where(e => e.Fecha_Solicitud == fecha_solicitud).First(); 
             } 

             //Se lee el código del indicador metabólico 
             string codigo = linea.Substring(236, 6).Trim(); 

             //Si en efecto el indicador presente en la línea que se está leyendo existe se prosigue a anexarlos al examen 
             if (indicadorrepo.ObtenerTodos().Where(i => i.Codigo == codigo).Count() != 0) 
             { 
              //Se carga el indicador con el que se está trabajando en una línea específica 
              Indicador_Metabolico indicador = indicadorrepo.ObtenerTodos().Where(i => i.Codigo == codigo).First(); 

              //Se crea una nueva instancia de valor metabólico 
              Valor_Metabolico val = new Valor_Metabolico(); 

              //Se obtienen los valores del indicador de la línea del archivo que se está leyendo 
              string rango_alto = linea.Substring(194, 6).Trim(); 
              string rango_bajo = linea.Substring(188, 6).Trim(); 
              string unidades = linea.Substring(178, 10).Trim(); 
              bool alerta = false; 
              string al = linea.Substring(200, 2).Trim(); 
              if (al != "") 
               alerta = true; 
              string valor = linea.Substring(118, 60).Trim(); 

              //Se inicializan los atributos del valor metabólico           
              //val.Examen_Metabolico_Id = examen.Id; 
              //val.Indicador_Metabolico_Id = indicador.Id; 
              val.Unidades = unidades; 
              val.Rango_Alto = rango_alto; 
              val.Rango_Bajo = rango_bajo; 
              val.Valor = valor; 
              val.Alerta = alerta; 
              val.Indicador_Metabolico = indicador; 
              examen.Valores_Metabolicos.Add(val); 
              historiarepo.GuardarTodo(); 
             } 
            } 
           } 
           stream.Close(); 
           file.MoveTo(Path.Combine(Server.MapPath("BackuplabtelFTP"), file.Name)); 
          } 
         } 
        } 
        catch (Exception e) 
        { 
         ViewData["Error"] = true; 
         return View(); 
        } 
        ViewData["Error"] = false; 
        return View(); 
       } 
       else 
       { 
        ViewData["sinActualizacionesPendientes"] = true; 
        return View(); 
       } 
      } 

     } 

ps。私はこのスクリプトを定期的に(1時間に1回)呼びたいと思っていますが、その方法もわかりません。

答えて

0

これはMVCで行う必要がありますか?これはおそらく、Windowsサービス(痛みのようなものかもしれません)やその他の種類のスケジュールされたアプリケーション、おそらくコンソールアプリケーションなどによって行われる可能性があります。ファイルシステムとDBのどちらかを行うだけの繰り返しタスクの場合は、System.Threading.Timersを使用するコンソールアプリケーションを使用します。あなたは、バックグラウンドタイマーのスレッドを動作させて、あなたのWebアプリケーションは、よく、Web物事を行うことができます:)

それはWebベースにする必要がある場合、ここで簡単な繰り返しタスクを行う方法の便利なポストです。

http://blog.stackoverflow.com/2008/07/easy-background-tasks-in-aspnet/

あなたは非同期アクションにあなたの行動をオンにしたい場合は、お使いのコントローラは、このようなものになります。

public class ScriptMetabolicoController : AsyncController 
    { 
     private IPortalAdministradorServices _servicioPortalAdministrador = new PortalAdministradorServices(); 

      IRepositorio<Historia> historiarepo = new Repositorio<Historia>(); 
     IRepositorio<Indicador_Metabolico> indicadorrepo = new Repositorio<Indicador_Metabolico>(); 

     [Authorize(Roles = "Administrador")] 
     public void IndexAsync() 
     { 
      AsyncManager.OutstandingOperations.Increment(); 

      DirectoryInfo myDir = new DirectoryInfo(Server.MapPath("labtelFTP")); 

      AsyncManager.Parameters["sinActualizacionesPendientes"] = false; 
      if (myDir.GetFiles().Count() != 0) 
      { 
       try 
       { 
        foreach (FileInfo file in myDir.GetFiles()) 
        { 
         if (file.Extension != ".aspx") 
         { 
          StreamReader stream; 
          stream = file.OpenText(); 

          while (stream.Peek() != -1) 
          { 
           string linea = stream.ReadLine(); 
           string cedula = linea.Substring(2, 18).Trim(); 
           Historia historia; 
           if (historiarepo.ObtenerTodos().Where(h => h.Cedula == cedula).Count() == 1) 
           { 
            //Se obtiene la historia por la cédula del participante 
            historia = historiarepo.ObtenerTodos().Where(h => h.Cedula == cedula).First(); 

            //Se inicializan las fechas de solicitud y las fechas de reporte del examen que se lee del archivo 
            var numero = historia.Examenes_Metabolicos.Count(); 

            int anor = Convert.ToInt32(linea.Substring(216, 4)); 
            int mesr = Convert.ToInt32(linea.Substring(220, 2)); 
            int diar = Convert.ToInt32(linea.Substring(222, 2)); 
            DateTime fecha_reporte = new DateTime(anor, mesr, diar); 

            int anos = Convert.ToInt32(linea.Substring(202, 4)); 
            int mess = Convert.ToInt32(linea.Substring(206, 2)); 
            int dias = Convert.ToInt32(linea.Substring(208, 2)); 
            DateTime fecha_solicitud = new DateTime(anos, mess, dias); 

            //Variable que tendrá el examen en cuestión 
            Examen_Metabolico examen; 

            //Si es el primer indicador de un examen nuevo en la historia del participante se crea una instancia nueva 
            if (historia.Examenes_Metabolicos.Where(e => e.Fecha_Solicitud == fecha_solicitud).Count() == 0) 
            { 

             examen = new Examen_Metabolico(); 
             examen.Fecha_Reporte = fecha_reporte; 
             examen.Fecha_Solicitud = fecha_solicitud; 
             historia.Examenes_Metabolicos.Add(examen); 

             //Se crea en base de datos el examen vacío para luego agregarle valores metabólicos asociados a el. 
             //historiarepo.GuardarTodo(); 
            } 
            //Si el indicador no es el primero de un examen nuevo entonces se le asigna a la variable 'examen' la referencia del mismo 
            else 
            { 
             examen = historia.Examenes_Metabolicos.Where(e => e.Fecha_Solicitud == fecha_solicitud).First(); 
            } 

            //Se lee el código del indicador metabólico 
            string codigo = linea.Substring(236, 6).Trim(); 

            //Si en efecto el indicador presente en la línea que se está leyendo existe se prosigue a anexarlos al examen 
            if (indicadorrepo.ObtenerTodos().Where(i => i.Codigo == codigo).Count() != 0) 
            { 
             //Se carga el indicador con el que se está trabajando en una línea específica 
             Indicador_Metabolico indicador = indicadorrepo.ObtenerTodos().Where(i => i.Codigo == codigo).First(); 

             //Se crea una nueva instancia de valor metabólico 
             Valor_Metabolico val = new Valor_Metabolico(); 

             //Se obtienen los valores del indicador de la línea del archivo que se está leyendo 
             string rango_alto = linea.Substring(194, 6).Trim(); 
             string rango_bajo = linea.Substring(188, 6).Trim(); 
             string unidades = linea.Substring(178, 10).Trim(); 
             bool alerta = false; 
             string al = linea.Substring(200, 2).Trim(); 
             if (al != "") 
              alerta = true; 
             string valor = linea.Substring(118, 60).Trim(); 

             //Se inicializan los atributos del valor metabólico           
             //val.Examen_Metabolico_Id = examen.Id; 
             //val.Indicador_Metabolico_Id = indicador.Id; 
             val.Unidades = unidades; 
             val.Rango_Alto = rango_alto; 
             val.Rango_Bajo = rango_bajo; 
             val.Valor = valor; 
             val.Alerta = alerta; 
             val.Indicador_Metabolico = indicador; 
             examen.Valores_Metabolicos.Add(val); 
             historiarepo.GuardarTodo(); 
            } 
           } 
          } 
          stream.Close(); 
          file.MoveTo(Path.Combine(Server.MapPath("BackuplabtelFTP"), file.Name)); 
         } 
        } 
         AsyncManager.Parameters["Error"] = false; 
       } 
       catch (Exception e) 
       { 
        AsyncManager.Parameters["Error"] = true; 
       } 
      } 
      else 
      { 
       AsyncManager.Parameters["sinActualizacionesPendientes"] = true; 
      } 


      AsyncManager.OutstandingOperations.Decrement(); 
     } 


     public ActionResult IndexCompleted(bool error, bool sinActualizacionesPendientes) 
     { 
      ViewData["sinActualizacionesPendientes"] = sinActualizacionesPendientes; 
      ViewData["Error"] = error; 
      return View(); 
     } 

    } 

そして、ここではあなたを助けることができるMSの記事ですが

http://msdn.microsoft.com/en-us/library/ee728598.aspx

これが役に立ちます。

+0

私はオプションだと思いますが、asyncControllerという機能があることを考えれば、この方法を改善するには良いアプローチかもしれないと思いました。 – ignaciofuentes

+0

長時間実行しているプロセスであれば、非同期で処理する方が間違いなく良いでしょう。 MSからの助言は次のとおりです。 操作は、CPUバインドの代わりにネットワークバインドまたはI/Oバインドされています。 テストでは、ブロック操作がサイトのパフォーマンスのボトルネックとなり、IISがこれらのブロッキング呼び出しに対して非同期アクションメソッドを使用してさらに多くの要求を処理できることが示されています。 並列性はコードの単純さよりも重要です。 長時間実行している要求をユーザーがキャンセルできるようにするメカニズムを提供する必要があります。 – mymex1

+0

それから私の質問は..私はそれをどうやってやるのだろう? – ignaciofuentes

0

これを確認してください。http://quartznet.sourceforge.net/私は現在のプロジェクトでこれを使用して、より長時間実行されるタスクをスケジュールする予定です。

関連する問題