我一直在使用Subsonic 3.0.0.4(ActiveRecord方法)一段时间,我最近编写了一个小页面,它基本上检索了给定年份的大约500条记录,然后我只是遍历每一条记录,创建新的Active Record类的实例,只修改Period字段,并在循环中保存每个实例。
问题是在执行该页面后,SQL服务器中挂起/打开了很多SQL连接(通过查看sp_who2)。在页面完成执行之前,我得到“Timeout expired。在从池中获取连接之前已经过了超时时间。这可能是因为所有池连接都在使用中并且达到了最大池大小。”错误。
代码如下:
if(string.IsNullOrEmpty(tbPeriodoAGenerar.Text))return;
var idPeriodo = Convert.ToInt32(tbPeriodoAGenerar.Text);
var nuevaEncuesta = new Encuesta();
nuevaEncuesta.IdPeriodo = idPeriodo;
nuevaEncuesta.IdResponsable = 1;
nuevaEncuesta.fechaCierre1 = Convert.ToDateTime(dpFechaCierre1.Value);
nuevaEncuesta.fechaCierre2 = Convert.ToDateTime(dpFechaCierre2.Value);
nuevaEncuesta.IdTipoEncuesta = (int)ETipoEncuesta.PorAnio;
nuevaEncuesta.nombreEncuesta = NombresEncuestas.COVA;
nuevaEncuesta.nombrePublico = NombresEncuestas.COVA_PUBLICO;
nuevaEncuesta.Save();
var empresasActivas = Empresa.Find(x => x.activo == 1);
foreach (var empresa in empresasActivas)
{
EmpresaEncuesta ee = new EmpresaEncuesta();
ee.IdEmpresa = empresa.IdEmpresa;
ee.IdEncuesta = nuevaEncuesta.IdEncuesta;
ee.IdEstatusContestado = (int)EEstatusEmpresaEncuesta.SinContestar;
ee.fechaMod = DateTime.Now;
ee.IdUsuario = 1;
ee.ipMod = IpUsuarioActual;
ee.Save();
}
if (chkMigrarRespuestas.Checked)
{
var periodosAnteriores = new EncuestaBO().ObtenerPeriodosAnteriores(NombresEncuestas.COVA, idPeriodo);
int? periodoAnterior = null;
if (periodosAnteriores.Tables[0].Rows.Count > 0)
{
periodoAnterior = Convert.ToInt32(periodosAnteriores.Tables[0].Rows[0][Columnas.ID_PERIODO]);
}
if (!periodoAnterior.HasValue) return;
var respuestasCortoPlazo = COVACortoPlazo.Find(x => x.Periodo == (periodoAnterior));
COVACortoPlazo ccp;
foreach (var ccpAnterior in respuestasCortoPlazo)
{
if (!empresasActivas.Where(emp => emp.IdEmpresa == ccpAnterior.IdEmpresa).Any()) continue;
ccp = new COVACortoPlazo();
ccp.IdEmpresa = ccpAnterior.IdEmpresa;
ccp.CuentaCortoPlazo = ccpAnterior.CuentaCortoPlazo;
ccp.ComentariosAdicionales = ccpAnterior.ComentariosAdicionales;
ccp.RetiroVoluntarioOpcionId = ccpAnterior.RetiroVoluntarioOpcionId;
ccp.RetiroVoluntarioOtroDesc = ccpAnterior.RetiroVoluntarioOtroDesc;
ccp.RetiroEmpresaOpcionId = ccpAnterior.RetiroEmpresaOpcionId;
ccp.RetiroEmpresaOtroDesc = ccpAnterior.RetiroEmpresaOtroDesc;
ccp.Periodo = idPeriodo;
ccp.Save();
}
var tablaCortoPlazoAnterior = COVATablaCortoPlazo.Find(x => x.Periodo == (periodoAnterior));
COVATablaCortoPlazo ctcp;
foreach (var ctcpAnterior in tablaCortoPlazoAnterior)
{
if (!empresasActivas.Where(emp => emp.IdEmpresa == ctcpAnterior.IdEmpresa).Any()) continue;
ctcp = new COVATablaCortoPlazo();
ctcp.IdEmpresa = ctcpAnterior.IdEmpresa;
ctcp.Periodo = idPeriodo;
ctcp.COVASegmentoOpcionId = ctcpAnterior.COVASegmentoOpcionId;
ctcp.NivelDinamicaMin = ctcpAnterior.NivelDinamicaMin;
ctcp.NivelDinamicaMax = ctcpAnterior.NivelDinamicaMax;
ctcp.NombreBono = ctcpAnterior.NombreBono;
ctcp.COVAPeriodicidadOpcionId = ctcpAnterior.COVAPeriodicidadOpcionId;
ctcp.MetodoCalculo = ctcpAnterior.MetodoCalculo;
ctcp.COVABaseCalculoOpcionId = ctcpAnterior.COVABaseCalculoOpcionId;
ctcp.RealAnualizado = ctcpAnterior.RealAnualizado;
ctcp.Save();
}
var respuestasAnual = COVAAnual.Find(x => x.Periodo == (periodoAnterior));
COVAAnual ca;
foreach (var caAnterior in respuestasAnual)
{
if (!empresasActivas.Where(emp => emp.IdEmpresa == caAnterior.IdEmpresa).Any()) continue;
ca = new COVAAnual();
ca.IdEmpresa = caAnterior.IdEmpresa;
ca.CuentaAnual = caAnterior.CuentaAnual;
ca.NombreBono = caAnterior.NombreBono;
ca.FechaPago = caAnterior.FechaPago;
ca.ComentariosAdicionales = caAnterior.ComentariosAdicionales;
ca.RetiroVoluntarioOpcionId = caAnterior.RetiroVoluntarioOpcionId;
ca.RetiroVoluntarioOtroDesc = caAnterior.RetiroVoluntarioOtroDesc;
ca.RetiroEmpresaOpcionId = caAnterior.RetiroEmpresaOpcionId;
ca.RetiroEmpresaOtroDesc = caAnterior.RetiroEmpresaOtroDesc;
ca.Periodo = idPeriodo;
ca.Save();
}
var tablaAnualAnterior = COVATablaAnual.Find(x => x.Periodo == (periodoAnterior));
COVATablaAnual cta;
foreach (var ctaAnterior in tablaAnualAnterior)
{
if (!empresasActivas.Where(emp => emp.IdEmpresa == ctaAnterior.IdEmpresa).Any()) continue;
cta = new COVATablaAnual();
cta.IdEmpresa = ctaAnterior.IdEmpresa;
cta.Periodo = idPeriodo;
cta.COVASegmentoOpcionId = ctaAnterior.COVASegmentoOpcionId;
cta.NivelDinamicaMin = ctaAnterior.NivelDinamicaMin;
cta.NivelDinamicaMax = ctaAnterior.NivelDinamicaMax;
cta.Minimo = ctaAnterior.Minimo;
cta.Target = ctaAnterior.Target;
cta.Maximo = ctaAnterior.Maximo;
cta.RealAnualPagado = ctaAnterior.RealAnualPagado;
cta.MetodoCalculo = ctaAnterior.MetodoCalculo;
cta.COVABaseCalculoOpcionId = ctaAnterior.COVABaseCalculoOpcionId;
cta.Save();
}
var respuestasLargoPlazo = COVALargoPlazo.Find(x => x.Periodo == (periodoAnterior));
COVALargoPlazo clp;
foreach (var clpAnterior in respuestasLargoPlazo)
{
if (!empresasActivas.Where(emp => emp.IdEmpresa == clpAnterior.IdEmpresa).Any()) continue;
clp = new COVALargoPlazo();
clp.IdEmpresa = clpAnterior.IdEmpresa;
clp.CuentaLargoPlazo = clpAnterior.CuentaLargoPlazo;
clp.ComentariosAdicionales = clpAnterior.ComentariosAdicionales;
clp.RetiroVoluntarioOpcionId = clpAnterior.RetiroVoluntarioOpcionId;
clp.RetiroVoluntarioOtroDesc = clpAnterior.RetiroVoluntarioOtroDesc;
clp.RetiroEmpresaOpcionId = clpAnterior.RetiroEmpresaOpcionId;
clp.RetiroEmpresaOtroDesc = clpAnterior.RetiroEmpresaOtroDesc;
clp.PermiteCompraAcciones = clpAnterior.PermiteCompraAcciones;
clp.Periodo = idPeriodo;
clp.Save();
}
var tablaLargoPlazoAnterior = COVATablaLargoPlazo.Find(x => x.Periodo == (periodoAnterior));
COVATablaLargoPlazo ctlp;
foreach (var ctlpAnterior in tablaLargoPlazoAnterior)
{
if (!empresasActivas.Where(emp => emp.IdEmpresa == ctlpAnterior.IdEmpresa).Any()) continue;
ctlp = new COVATablaLargoPlazo();
ctlp.IdEmpresa = ctlpAnterior.IdEmpresa;
ctlp.Periodo = idPeriodo;
ctlp.NombrePlan = ctlpAnterior.NombrePlan;
ctlp.COVATipoPlanOpcionId = ctlpAnterior.COVATipoPlanOpcionId;
ctlp.COVASegmentoOpcionId = ctlpAnterior.COVASegmentoOpcionId;
ctlp.NivelDinamicaMin = ctlpAnterior.NivelDinamicaMin;
ctlp.NivelDinamicaMax = ctlpAnterior.NivelDinamicaMax;
ctlp.RealPagadoFinalPlan = ctlpAnterior.RealPagadoFinalPlan;
ctlp.AniosEjerce = ctlpAnterior.AniosEjerce;
ctlp.MetodoCalculo = ctlpAnterior.MetodoCalculo;
ctlp.BaseCalculo = ctlpAnterior.BaseCalculo;
ctlp.Save();
}
var respuestasVentas = COVAVentas.Find(x => x.Periodo == (periodoAnterior));
COVAVentas cv;
foreach (var cvAnterior in respuestasVentas)
{
if (!empresasActivas.Where(emp => emp.IdEmpresa == cvAnterior.IdEmpresa).Any()) continue;
cv = new COVAVentas();
cv.IdEmpresa = cvAnterior.IdEmpresa;
cv.CuentaVentas = cvAnterior.CuentaVentas;
cv.ComentariosAdicionales = cvAnterior.ComentariosAdicionales;
cv.RetiroVoluntarioOpcionId = cvAnterior.RetiroVoluntarioOpcionId;
cv.RetiroVoluntarioOtroDesc = cvAnterior.RetiroVoluntarioOtroDesc;
cv.RetiroEmpresaOpcionId = cvAnterior.RetiroEmpresaOpcionId;
cv.RetiroEmpresaOtroDesc = cvAnterior.RetiroEmpresaOtroDesc;
cv.Periodo = idPeriodo;
cv.Save();
}
var tablaVentasAnterior = COVATablaVentas.Find(x => x.Periodo == (periodoAnterior));
COVATablaVentas ctv;
foreach (var ctvAnterior in tablaVentasAnterior)
{
if (!empresasActivas.Where(emp => emp.IdEmpresa == ctvAnterior.IdEmpresa).Any()) continue;
ctv = new COVATablaVentas();
ctv.IdEmpresa = ctvAnterior.IdEmpresa;
ctv.Periodo = idPeriodo;
ctv.COVASegmentoOpcionId = ctvAnterior.COVASegmentoOpcionId;
ctv.COVAPeriodicidadOpcionId = ctvAnterior.COVAPeriodicidadOpcionId;
ctv.Minimo = ctvAnterior.Minimo;
ctv.Target = ctvAnterior.Target;
ctv.Maximo = ctvAnterior.Maximo;
ctv.RealAnualizado = ctvAnterior.RealAnualizado;
ctv.MetodoCalculo = ctvAnterior.MetodoCalculo;
ctv.BaseCalculo = ctvAnterior.BaseCalculo;
ctv.Save();
}
var respuestasGenerales = COVAGenerales.Find(x => x.Periodo == (periodoAnterior));
COVAGenerales cg;
foreach (var cgAnterior in respuestasGenerales)
{
if (!empresasActivas.Where(emp => emp.IdEmpresa == cgAnterior.IdEmpresa).Any()) continue;
cg = new COVAGenerales();
cg.IdEmpresa = cgAnterior.IdEmpresa;
cg.AccionesPorSituacionActual = cgAnterior.AccionesPorSituacionActual;
cg.ComentariosAccionesSituacionActual = cgAnterior.ComentariosAccionesSituacionActual;
cg.TomaCuentaSituacionDefinicionObjetivos = cgAnterior.TomaCuentaSituacionDefinicionObjetivos;
cg.Periodo = idPeriodo;
cg.Save();
}
}
我做错了吗?此时,我不确定这是否是一个亚音速错误,或者我是否需要以某种方式手动关闭连接。
在使用亚音速时,我搜索了有关类似问题的帖子,但没有一个出现过。我得到错误的常见原因是没有关闭SqlDataReader,但老实说我不相信Subsonic没有关闭它......我使用的是最新版本。
有什么想法吗?非常感谢任何帮助。
答案 0 :(得分:2)
每当你对基于ORM的对象进行循环时,你必须考虑可能存在N + 1问题。我看不到你的模型,但我敢打赌,在你的循环中,你正在执行一些额外的查询。
我知道Save()会触发并关闭一个ExecuteScalar() - 这不应该打开一个连接。但是,如果您在该循环中获取相关记录 - 是的,那可能会有问题。
所以 - 我建议使用某种类型的探查器和调试器来逐步完成循环 - 看看有什么查询。
或者 - 这对于使用BatchInsert的东西来说已经成熟,它可以将所有内容保存在一个漂亮,整洁的单连接事务中。
请阅读此处了解更多信息: http://subsonic.wekeroad.com/docs/Linq_Inserts