Subsonic 3.0.0.4 leaking SQL connections? - activerecord

I've been using Subsonic 3.0.0.4 (ActiveRecord approach) for a while, and I recently coded a small page that basically retrieves about 500 records for a given year, and then i just loop through each of them, creating new instances of the Active Record class, just modifying the Period field, and saving each instance in the loop.
The issue is that after executing that page, a LOT of SQL connections are left hanging/open in SQL server (by looking at the sp_who2). Before the page finishes executing, I get the "Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached." error.
The code is the following:
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();
}
}
Am I doing it the wrong way? At this point, I am not sure if this is a Subsonic bug or if I need to manually close the connection myself somehow.
I've googled for posts about similar problems when using subsonic, but none have come up. The usual cause for the error I get is not closing the SqlDataReader, but I honestly do not believe Subsonic is not closing it..and Im using the latest version.
Any ideas? Any help is greatly appreciated.

Any time you have a loop on an ORM-based object you have to consider there's probably an N+1 issue. I can't see your model, but I'll bet that in your loop you're executing a number of additional queries.
I know that Save() fires and closes an ExecuteScalar() - this should not leave a connection open. However, if you're fetching related records inside that loop - yeah that could have problems.
So - I would recommend using a profiler of some kind and the debugger to step through your loop - see what queries are made.
Alternatively - this is ripe for using the BatchInsert stuff which would keep everything in a nice, tidy single-connection transaction.
Read here for more:
http://subsonic.wekeroad.com/docs/Linq_Inserts

Related

Linq # Where clause with multiple condition

this is my export ui
this is my code:
var wrlist = db.Tbl_WorkRequest.ToList().Where(c => c.WR_Status == wrstatus &&
(wrtype.Length != 0) &&
c.WR_Family == wrfamily &&
wrfamily.Length!=0)
.Select(d => new {
WR_Title = d.WR_Title.ToString(),
WR_Type = d.WR_Type.ToString(),
WR_Family = d.WR_Family.ToString(),
WR_Status = d.WR_Status.ToString(),
WR_LocationAsset = d.WR_LocationAsset.ToString(),
WR_AssetName = d.WR_AssetName.ToString(),
WR_Requestor = d.WR_Requestor.ToString()
});
the problem is if I only choose zone in dropdownlist:family it generates correct list.
but when I choose dropdownlist:family&status it generates nothing.
this is the table:
I would change your code to check each filter criteria and add the appropriate filter, then convert to a list:
var wrq = db.Tbl_WorkRequest.AsQueryable();
if (wrstatus.Length > 0)
wrq = wrq.Where(wr => wr.WR_Status == wrstatus);
if (wrfamily.Length > 0)
wrq = wrq.Where(wr => wr.WR_Family == wrfamily);
var wrlist = wrq.Select(d => new {
WR_Title = d.WR_Title.ToString(),
WR_Type = d.WR_Type.ToString(),
WR_Family = d.WR_Family.ToString(),
WR_Status = d.WR_Status.ToString(),
WR_LocationAsset = d.WR_LocationAsset.ToString(),
WR_AssetName = d.WR_AssetName.ToString(),
WR_Requestor = d.WR_Requestor.ToString()
})
.ToList();

I want to Group questions and answers LINQ and have them display properly

I'm trying to group properly to have my cell distribute eveningly. The printout is coming very odd and uneven.
is it the table i'm creating or group or both? I think the group is correct. My results are as shown in the image below.
Gold is the heading,
Green are the questions,
Red are the answers
Mt table is is below
var Sections = new OncologySection().SelectSections(projectID.ToString());
int iSection = 0;
int igroups = 0;
int ianswer = 0;
tb.CssClass = "";
tb.BorderWidth = 1;
tb.Width = new Unit("780px");
tb.Attributes.Add("runat", "server");
foreach (OncologySection section in Sections)
{
TableRow row1 = new TableRow();
iSection++;
// var getDistinctQuestion = getVoterAnswerstoList.Select(s => s.QuestionText ,s.Id).Distinct().ToList();
var getVoterAnswerstoList = new OncologyGeneratePDFDAL().DataforPDFCreation(Convert.ToInt32(projectID), Convert.ToInt32(voterid), Convert.ToInt32(caseId), Convert.ToInt32(voteSurveyId), Convert.ToInt32(section.SectionID)).OrderBy(os => os.SortOrder);
//var groupedCustomerList = getVoterAnswerstoList
// .GroupBy(u => u.QuestionText, u.QuestionText)
// .Select(grp => grp.ToList())
// .ToList();
var groupedCustomerList = getVoterAnswerstoList.GroupBy(x => new { x.QuestionText, x.DynamicValue }).ToList();
TableCell cell1 = new TableCell();
cell1.BorderWidth = 1;
cell1.Text = section.SectionName;
cell1.BorderColor = System.Drawing.Color.Goldenrod;
cell1.ColumnSpan = groupedCustomerList.Count();
row1.Cells.Add(cell1);
tb.Rows.Add(row1);
TableRow row2 = new TableRow();
foreach (var groups in groupedCustomerList)
{
igroups++;
TableCell cell2 = new TableCell();
var q = (from s in groups select s.QuestionText).FirstOrDefault();
cell2.BorderWidth = 1;
cell2.Text = q;
cell2.BorderColor = System.Drawing.Color.Green;
cell2.ColumnSpan = groupedCustomerList.Count();
row2.Cells.Add(cell2);
if (igroups == groupedCustomerList.Count())
{
tb.Rows.Add(row2);
}
else
{
row2.Cells.Add(cell2);
}
TableRow row3 = new TableRow();
foreach (var answers in groups)
{
ianswer++;
TableCell cell3 = new TableCell();
cell3.BorderWidth = 1;
cell3.BorderColor = System.Drawing.Color.DarkRed;
if (answers.DataTypeId == 7)
{
cell3.Text = answers.DynamicValue.ToString();
}
else if ((answers.DataTypeId == 5) || (answers.DataTypeId == 6) || (answers.DataTypeId == 8))
{
if (answers.VotingValue != 0)
{
cell3.Text = answers.VotingValue.ToString();
}
else
{
cell3.Text = " ";
}
}
else
{
cell3.Text = " ";
}
row3.Cells.Add(cell3);
tb.Rows.Add(row3);
}
}
}
}

linq sum of multiple values

i need to get the sum of billableHours and nonBillableHours.
this is my code.
var currentMonth = 10;
var userQuery =
from timeEntry in TimeEntries
join ta in Tasks on timeEntry.TaskID equals ta.TaskID
where timeEntry.DateEntity.Month == currentMonth && timeEntry.DateEntity.Year == DateTime.Today.Year
select new
{
HoursEntered = timeEntry.HoursEntered,
Billable = ta.Billable
};
var localrows = userQuery.ToList();
var grouping = localrows.GroupBy(x => x.Billable);
var userList = grouping.Select(q => new
{
billableHours = q.Where(x=> x.Billable == true),
nonBillableHours = q.Where(x=> x.Billable != true)
});
i cannot seem to find a way to get the sum.
I need the sum of those two columns, so i can call them,
and calculate values i get from them.
When you need more than one aggregate, you can still get the result with a single query by using group by constant technique. Which in this specific case can be combined with conditional Sum:
var hoursInfo =
(from timeEntry in TimeEntries
join ta in Tasks on timeEntry.TaskID equals ta.TaskID
where timeEntry.DateEntity.Month == currentMonth && timeEntry.DateEntity.Year == DateTime.Today.Year
group new { timeEntry.HoursEntered, ta.Billable } by 1 into g
select new
{
BillableHours = g.Sum(e => e.Billable ? e.HoursEntered : 0),
NonBillableHours = g.Sum(e => !e.Billable ? e.HoursEntered : 0),
}).FirstOrDefault();
You do not need to group them. Try this query:
var userQuery =
from timeEntry in TimeEntries
join ta in Tasks on timeEntry.TaskID equals ta.TaskID
where timeEntry.DateEntity.Month == currentMonth
&& timeEntry.DateEntity.Year == DateTime.Today.Year
select new
{
HoursEntered = timeEntry.HoursEntered,
Billable = ta.Billable
};
var billableHours = userQuery
.Where(m => m.Billable) // Billable
.Select(m => m.HoursEntered)
.DefaultIfEmpty(0)
.Sum();
var nonBillableHours = userQuery
.Where(m => !m.Billable) // Non-bilable
.Select(m => m.HoursEntered)
.DefaultIfEmpty(0)
.Sum();
var currentMonth = 10;
var TimeEntries = new List<TimeEntry>() {
new TimeEntry(){TaskID = 1,DateEntity = DateTime.Now.AddDays(1),HoursEntered =2},
new TimeEntry(){TaskID = 2,DateEntity = DateTime.Now.AddDays(2),HoursEntered =3},
new TimeEntry(){TaskID = 3,DateEntity = DateTime.Now.AddDays(3),HoursEntered =2},
new TimeEntry(){TaskID = 4,DateEntity = DateTime.Now.AddDays(4),HoursEntered =4},
new TimeEntry(){TaskID = 5,DateEntity = DateTime.Now.AddDays(5),HoursEntered =2},
new TimeEntry(){TaskID = 6,DateEntity = DateTime.Now.AddDays(6),HoursEntered =6}
};
var UserTasks = new List<UserTask>(){
new UserTask(){TaskID = 1,Billable = true} ,
new UserTask(){TaskID = 2,Billable = false} ,
new UserTask(){TaskID = 3,Billable = true} ,
new UserTask(){TaskID = 4,Billable = false} ,
new UserTask(){TaskID = 5,Billable = true} ,
new UserTask(){TaskID = 6,Billable = false}
};
var userQuery =
from x in
(from timeEntry in TimeEntries
join ta in UserTasks on timeEntry.TaskID equals ta.TaskID
where timeEntry.DateEntity.Month == currentMonth && timeEntry.DateEntity.Year == DateTime.Today.Year
select new
{
HoursEntered = timeEntry.HoursEntered,
Billable = ta.Billable
})
group x by x.Billable into g
select new
{
IsBillable = g.Key,
Billabe = g.Where(t => t.Billable == true).Sum(x => x.HoursEntered),
NonBillable = g.Where(t => t.Billable == false).Sum(x => x.HoursEntered)
};
foreach (var item in userQuery.ToList())
{
Console.WriteLine(string.Format("{0} - {1}", item.IsBillable? "Billable":"Non-Billable",item.IsBillable?item.Billabe:item.NonBillable));
}

Convert query to lambda

I want to know how can I write this query:
var query = from p in context.DimProduct
from psc in context.DimProductSubcategory
// on psc.ProductCategoryKey equals pc.ProductCategoryKey
where psc.EnglishProductSubcategoryName == subCategoryName
&& psc.ProductSubcategoryKey == p.ProductSubcategoryKey
select new DimProductDTO
{
ProductKey = p.ProductKey,
ProductSubcategoryKey = p.ProductSubcategoryKey,
EnglishProductName = p.EnglishProductName,
Size = p.Size,
StandardCost = p.StandardCost
};
I tried some queries, but no success. My problem is that I don't know how to have access to DimProduct and DimProductSubcategory.
Any suggestions?
context.DimProduct
.SelectMany(p => new { p, psc = context.DimProductSubcategory })
.Where(x => x.psc.EnglishProductSubcategoryName == subCategoryName
&& x.psc.ProductSubcategoryKey == x.p.ProductSubcategoryKey)
.Select(x => new DimProductDTO {
ProductKey = x.p.ProductKey,
ProductSubcategoryKey = x.p.ProductSubcategoryKey,
EnglishProductName = x.p.EnglishProductName,
Size = x.p.Size,
StandardCost = x.p.StandardCost })
However, you're not selecting anything from DimProductSubcategory, so I think the same can be done using Any() extension method:
context.DimProduct
.Where(x => context.DimProductSubcategory
.Any(y => y.EnglishProductSubcategoryName == subCategoryName
&& y.ProductSubcategoryKey == x.ProductSubcategoryKey))
.Select(x => new DimProductDTO {
ProductKey = x.ProductKey,
ProductSubcategoryKey = x.ProductSubcategoryKey,
EnglishProductName = x.EnglishProductName,
Size = x.Size,
StandardCost = x.StandardCost });
It should generate IN SQL statement within the query.
That is not exactly same query, but it produces same result via inner join (I believe that is more efficient than cross join)
context.DimProduct
.Join(context.DimProductSubcategory
.Where(x => x.EnglishProductSubcategoryName == subCategoryName),
p => ProductSubcategoryKey,
psc => ProductSubcategoryKey,
(p,psc) => new { p, psc })
.Select(x => new DimProductDTO {
ProductKey = x.p.ProductKey,
ProductSubcategoryKey = x.p.ProductSubcategoryKey,
EnglishProductName = x.p.EnglishProductName,
Size = x.p.Size,
StandardCost = x.p.StandardCost })
Also your original query can be rewritten as
var query = from p in context.DimProduct
join psc in context.DimProductSubcategory
on p.ProductSubcategoryKey equals psc.ProductSubcategoryKey
where psc.EnglishProductSubcategoryName == subCategoryName
select new DimProductDTO {
ProductKey = p.ProductKey,
ProductSubcategoryKey = p.ProductSubcategoryKey,
EnglishProductName = p.EnglishProductName,
Size = p.Size,
StandardCost = p.StandardCost
};
Generated SQL will look like:
SELECT [t0].[ProductKey], [t0].[ProductSubcategoryKey]
FROM [DimProduct] AS [t0]
INNER JOIN [DimProductSubcategory] AS [t1]
ON [t0].[EnglishProductSubcategoryName] = [t1].[ProductSubcategoryKey]
WHERE [t1].[EnglishProductSubcategoryName] = #p0

Entity fails on simulataneous AJAX posts

I have an action that updates the database based on a Jquery Droppable/Sortable. The first AJAX post works fine, but the second one gives me the error:
New transaction is not allowed because there are other
threads running in the session.
It's being posted to 2 separate actions on the same controller, using the same UnitOfWork in the controller. Not sure what I have to do to fix this.
EDIT: these are the two service methods being called:
public void NavItemSort(List<string> orderArray, string navID, string subNavID)
{
var newOrderArray = orderArray.Where(s => !string.IsNullOrWhiteSpace(s)).ToList();
var orderArrayIDs = newOrderArray.Select(x => x.Replace("ContentItem", "")).ToList();
var itemToBeSorted = Convert.ToInt32(orderArrayIDs.FirstOrDefault());
var itemContext = cmsUnitOfWork.NavigationItems.Find().Where(x => x.ID == itemToBeSorted).ToList().FirstOrDefault();
var currentSortOrder = cmsUnitOfWork.NavigationItems.Find()
.Where(x => x.NavID == itemContext.NavID &&
(itemContext.ParentID == null) ? x.ParentID == null :
x.ParentID == itemContext.ParentID).ToList();
var existingItems = currentSortOrder.Select(x => x.ID).ToList();
List<string> existingItemsString = existingItems.ConvertAll<string>(x => x.ToString()).ToList();
var newNavItemID = existingItemsString.Except(orderArray).FirstOrDefault();
var currentSortOrderExcept = currentSortOrder.Where(x => x.ID != Convert.ToInt32(newNavItemID));
foreach (var x in currentSortOrderExcept)
{
int sortOrderInt = orderArrayIDs.IndexOf(orderArrayIDs.Where(z => int.Parse(z) == x.ID).ToList().FirstOrDefault()) + 1;
NavigationItem navigationItem = new NavigationItem()
{
HasChild = x.HasChild,
Level = x.Level,
NavID = x.NavID,
ID = x.ID,
ParentID = x.ParentID,
PageID = x.PageID,
URL = x.URL,
Title = x.Title,
SortOrder = sortOrderInt,
};
if (navigationItem.SortOrder != null && navigationItem.SortOrder != 0)
{
cmsUnitOfWork.NavigationItems.Update(x, navigationItem);
}
}
cmsUnitOfWork.Commit();
}
public void NavItemAdd(List<string> orderArray, string NavID, string subNavID){
var newOrderArray = orderArray.Where(s => !string.IsNullOrWhiteSpace(s)).ToList();
var orderArrayIDs = newOrderArray.Select(x => x.Replace("ContentItem", "")).ToList();
NavID = NavID.Replace("nav", "");
int NavIDInt = int.Parse(NavID);
int subNavIDInt = int.Parse(subNavID);
var existingNavItems = cmsUnitOfWork.NavigationItems.Find().Where(x => x.NavID == NavIDInt && x.ParentID == subNavIDInt).ToList();
int currentSortOrder = 0;
if (existingNavItems.Count() != 0)
{
currentSortOrder = existingNavItems.Max(x => x.SortOrder);
}
var existingItems = existingNavItems.Select(x => x.ID).ToList();
List<string> existingItemsString = existingItems.ConvertAll<string>(x => x.ToString()).ToList();
var newNavItemID = orderArray.Except(existingItemsString).FirstOrDefault();
int newNavIDInt = int.Parse(newNavItemID);
var newNavItemList = cmsUnitOfWork.NavigationItems.Find().Where(x => x.ID == newNavIDInt).ToList();
var newNavItem = newNavItemList.FirstOrDefault();
var parentNav = cmsUnitOfWork.NavigationItems.Find().Where(x => x.ID == subNavIDInt).ToList().FirstOrDefault();
NavigationItem navigationItemUpdated = new NavigationItem()
{
ID = newNavItem.ID,
Level = 2,
NavID = NavIDInt,
PageID = newNavItem.PageID,
Title = newNavItem.Title,
URL = newNavItem.URL,
ParentID = subNavIDInt,
SortOrder = currentSortOrder + 1
};
cmsUnitOfWork.NavigationItems.Update(newNavItem, navigationItemUpdated);
cmsUnitOfWork.Commit();
}
I'm guessing you started a transaction against that context and you never dispose of it not commit it. Just a guess though as you didn't Los any code (please post code)
Maybe you have declared cmsUnitOfWork as static variable? Context must be created and destroyed on each request

Resources