I currently have this huge and slow code that takes forever to run.... Im in the process of refactoring it to make it somewhat more readable and overall provide a faster experience... Basically I have a folder in my server where text files are stored with a LOT of data.. this script will read from this files and through EF add elements to the database... this takes a long time to load.
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 = stre开发者_开发百科am.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();
}
}
}
I know there is a feature called asynchronous controllers but Im not sure if they are meant for this case...
Please give me some advice on how to make this better.
ps. I would also like this script to be called regularly (once an hour) but Im not sure how to that either..
Does this need to be done in MVC? It seems like this could maybe be done by something like a windows service (which could be kind of a pain) or some other kind of scheduled app, maybe even a console application. For repeating tasks that just do things with either file systems or the DB, I use a console application that uses System.Threading.Timers. You let the background timer threads work and your web app is free to do, well, web things :)
If it needs to be web based, here's a handy post for how to do simple repeating tasks.
https://blog.stackoverflow.com/2008/07/easy-background-tasks-in-aspnet/
If you wanted to turn your action into an asynchronous action then your controller would look something like this:
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();
}
}
And here's the MS article that could help you out:
http://msdn.microsoft.com/en-us/library/ee728598.aspx
Hope this helps!
Check this out it may help http://quartznet.sourceforge.net/ . I plan on using it in my current project to schedule up some longer running tasks.
精彩评论