Why does this LINQ statement throw a timeout error? - c#

I am getting this error when I execute this line, through break points I detected this error.
Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
int? dressSerialNo;
var lstDress = (
from yy in currContext.OrderDressings
where yy.OrderID == this.OrderID
&& yy.OrderItemID == this.orderItemID
&& yy.ProductID == this.ProductID
select yy
).ToList();
if (lstDress.Count > 0)
{
dressSerialNo = (
from yy in lstDress
where yy.OrderID == this.OrderID
&& yy.OrderItemID == this.orderItemID
&& yy.ProductID == this.ProductID
select (int?)yy.SrNo
).Max();
dressSerialNo += dressSerialNo + 1;
}
else dressSerialNo = 1;
solution:- In my project I was mainlining transaction in two for some module old method with ado.net and for newly developed modules I was using the entity framework so it was creating problem in transaction. So it went aberrant.

You are using Linq-To-Entities. There is an issue with the connection to your database server. Common causes for this are:
The query is taking longer than the timeout specified in the context.
There are network related issues causing a delay.
You can optionally change the command timeout (see this question about how to do this).

You don't want to materialize your all your entities using .ToList().
You could write a single query that returns only what you're interested in:
// Get the entity that contains the max value, using Ordering
var myMaxIfAny = currContext.OrderDressings
.Where(yy => yy.OrderID == this.OrderID && yy.OrderItemID == this.orderItemID && yy.ProductID == this.ProductID)
.OrderByDescending(z => z.SrNo)
.FirstOrDefault();
if (myMaxIfAny != null)
{
// Then you got a value, retrieve the Max using myMaxIfAny.SrNo
// ...
}
else
{
// ...
}

I've formatted and commented your code:
int? dressSerialNo;
// Get all OrderDressings with matching OrderID, orderItemID and ProductID as a List<OrderDressing>
var lstDress = (from yy in currContext.OrderDressings
where yy.OrderID == this.OrderID
&& yy.OrderItemID == this.orderItemID
&& yy.ProductID == this.ProductID
select yy)
.ToList();
// If any were found,
if (lstDress.Count > 0)
{
// Execute the Where again (what else will the list contain?) and select all yy.SrNo
dressSerialNo = (from yy in lstDress
where yy.OrderID == this.OrderID
&& yy.OrderItemID == this.orderItemID
&& yy.ProductID == this.ProductID
select (int?)yy.SrNo)
.Max(); // And take the Max() of that
// Add dressSerialNo + 1 to dressSerialNo.
dressSerialNo += dressSerialNo + 1;
}
else dressSerialNo = 1;
Which seems it can be corrected and reduced to:
int? serialNumber = (from yy in currContext.OrderDressings
where yy.OrderID == this.OrderID
&& yy.OrderItemID == this.orderItemID
&& yy.ProductID == this.ProductID
select yy.SrNo)
.DefaultIfEmpty() // Might not be necessary
.Max();
if (!serialNumber.HasValue)
{
serialNumber = 1;
}
else
{
serialNumber++;
}
Please note this can cause concurrency issues if two people execute this at the same time.

The query against the database is taking too long. There are many reasons as to why this could be happening.
Try running the sql statement generated from the linq directly to the database to see if it takes as long.
Check and see if any of your columns have massive data. (like a string column filled with large volume of data)
Meanwhile try adding this to end of your connection string
Connection Timeout=30000;

I have found the issue it was creating time out problem,
in my application transaction was maintained in 2 style,
one with old ado.net style, and another with EF style,
so it created a chaos. I am to make it uniform all to change in entity-framework.

Related

How to avoid executing the else part of a conditional statement?

I have a function that is called to retrieve transactions by a specified start and end date. I am now updating this function to also return ALL transactions(start/end date are null) for certain cases.
When start and end date are null (which are properties of the TransactionsCriteria class) I need the last code block in the snippet below executed. I can't wrap that snippet of code in an if statement since I need it executed for other cases as well, when start and end date are NOT null.
How do I accomplish implementing this logic with the below code block?
Thank you.
public async Task<(int total, List<Transaction> records)> GetAllTransactionsAsync(int fundId, TransactionsCriteria criteria)
{
IQueryable<Transaction> transactions = _db.Transactions.Include(t => t.DepositSource).Include(t => t.WithdrawalSource).Include(t => t.ReconciliationReport).Where(t => t.FundId == fundId);
if (criteria.UseClearedDate)
{
transactions = transactions.Where(t => t.ReconciliationReport != null && (t.ReconciliationReport.DateCreated.Date >= criteria.StartDate.Date
&& t.ReconciliationReport.DateCreated.Date <= criteria.EndDate.Date));
}
if (criteria.Reconcile)
{
transactions = transactions.Where(t =>
t.Date.Date <= criteria.EndDate.Date);
}
else
{
transactions = transactions.Where(t =>
t.Date.Date >= criteria.StartDate.Date
&& t.Date.Date <= criteria.EndDate.Date);
}
transactions = transactions.Where(t => (criteria.Statuses.Contains(t.ReconciliationId == null ? t.IsVoided ? TransactionStatus.Void : TransactionStatus.Outstanding : TransactionStatus.Cleared))
&& criteria.Sources.Contains(t.TransactionSource) && criteria.Types.Contains(t.TransactionType));
By virtue of it being an if...else statement, matching the condition criteria.StartDate == null && criteria.EndDate == null causes it to enter the if block and skip the else block.

EF Count() > 0 but First() throws exception

I have faced a strange problem. When user comes to any page of my web app
I do check if user has permissions to access it, and provide trial period if its first time to come.
Here is my piece of code:
List<string> temp_workers_id = new List<string>();
...
if (temp_workers_id.Count > 6)
{
System.Data.SqlTypes.SqlDateTime sqlDate = new System.Data.SqlTypes.SqlDateTime(DateTime.Now.Date);
var rusers = dbctx.tblMappings.Where(tm => temp_workers_id.Any(c => c == tm.ModelID));
var permissions = dbctx.UserPermissions
.Where(p => rusers
.Any(ap => ap.UserID == p.UserID)
&& p.DateStart != null
&& p.DateEnd != null
&& p.DateStart <= sqlDate.Value
&& p.DateEnd >= sqlDate.Value);
if (permissions.Count() < 1)
{
permissions = dbctx.UserPermissions
.Where(p => rusers
.Any(ap => ap.UserID == p.UserID)
&& p.DateStart == null
&& p.DateEnd == null);
var used = dbctx.UserPermissions
.Where(p => rusers
.Any(ap => ap.UserID == p.UserID)
&& p.DateStart != null
&& p.DateEnd != null);
if (permissions.Count() > 0 && used.Count() < 1)
{
var p = permissions.First();
using (Models.TTTDbContext tdbctx = new Models.TTTDbContext())
{
var tp = tdbctx.UserPermissions.SingleOrDefault(tup => tup.UserID == p.UserID);
tp.DateStart = DateTime.Now.Date;
tp.DateEnd = DateTime.Now.Date.AddDays(60);
tdbctx.SaveChanges();
}
here the First() method throws exception:
Sequence contains no elements
how that even could be?
EDIT:
I dont think that user opens two browsers and navigate here at the same time, but could be the concurrency issue?
You claim you only found this in the server logs and didn't encounter it during debugging. That means that between these lines:
if (permissions.Count() > 0)
{
var p = permissions.First();
Some other process or thread changed your database, so that the query didn't match any documents anymore.
This is caused by permissions holding a lazily evaluated resource, meaning that the query is only executed when you iterate it (which Count() and First()) do.
So in the Count(), the query is executed:
SELECT COUNT(*) ... WHERE ...
Which returns, at that moment, one row. Then the data is modified externally, causing the next query (at First()):
SELECT n1, n2, ... WHERE ...
To return zero rows, causing First() to throw.
Now for how to solve that, is up to you, and depends entirely on how you want to model this scenario. It means the second query was actually correct: at that moment, there were no more rows that fulfilled the query criteria. You could materialize the query once:
permissions = query.Where(...).ToList()
But that would mean your logic operates on stale data. The same would happen if you'd use FirstOrDefault():
var permissionToApply = permissions.FirstOrDefault();
if (permissionToApply != null)
{
// rest of your logic
}
So it's basically a lose-lose scenario. There's always the chance that you're operating on stale data, which means that the next code:
tdbctx.UserPermissions.SingleOrDefault(tup => tup.UserID == p.UserID);
Would throw as well. So every time you query the database, you'll have to write the code in such a way that it can handle the records not being present anymore.

EF6 Get Record where info from two different tables equal x

I am guessing this is a JOIN issue - which I don't understand anyway.
but I have to get a Record from EUReporteds if the Where clause is correct and if the Where clause on another table is NOT correct.
The coding I am using is truly horrific
do
{
// Get the next Unprocessed.
if (skip == 0)
eur = de.EUReporteds.Where(r => r.Processed == false && r.ReportProcessingCount < 11).FirstOrDefault();
else
eur = de.EUReporteds.Where(r => r.Processed == false && r.ReportProcessingCount < 11).OrderBy(ob => ob.id).Skip(skip).FirstOrDefault();
// Have we personally already done this?
pr = de.ProcessingResults.Where(p => p.UserId == CurrentUser.UserId && p.id == eur.id).FirstOrDefault();
skip++;
} while (pr != null || eur == null); // If so repeat
So what I am trying to do here is:
Get a record from EUReporteds
WHERE the record has not been processed
AND WHERE the RecordProcessingCount is less than 11
Check to see if this logged in user has already processed that record by
Getting The ProcessingResults Record where The CurrentUser exists
AND WHERE the ID of EUReporteds also exists
IF ProcessingResults Record Exists then we have done this record find the next until The ProcessingResults record can not be found.
Could someone please show me how to write this properly please.
Try this(using linq):
var firstUnprocessedRecord = (from eur in de.EUReporteds
where !eur.Processed && eur.ReportProcessingCount < 11
&& !(de.ProcessingResults.Any(o=>o.UserId == CurrentUser.UserId && o.id == eur.id))
orderby eur.id
select eur).FirstOrDefault();

Using Linq to filter by List<ListItem>

I am trying to extend my linq query with additional search criteria to filter the data by sending also a List<Listitem> to the function for processing. The List can contain 1 or more items and the objective is to retreive all items which match any criteria.
Since i am sending several search criteria to the function the goal is to make a more accurate filter result the more information i am sending to the filter. If one or several criterias are empty then the filter will get less accurate results.
Exception is raised every time i execute following code, and I cant figure out how to solve the using statement to include the List<ListItem>. Appreciate all the help in advance!
Exception: Unable to create a constant value of type 'System.Web.UI.WebControls.ListItem'. Only primitive types or enumeration types are supported in this context.
using (var db = new DL.ENTS())
{
List<DL.PRODUCTS> products =
(from a in db.PRODUCTS
where (description == null || description == "" ||
a.DESCRIPTION.Contains(description)) &&
(active == null || active == "" || a.ACTIVE.Equals(active, StringComparison.CurrentCultureIgnoreCase)) &&
(mID == null || mID == "" || a.MEDIA_ID == mID) &&
(mID == null || objTypes.Any(s => s.Value == a.OBJECTS)) //Exception here!
select a).ToList<DL.PRODUCTS>();
return products;
}
Pass collection of primitive values to expression:
using (var db = new DL.ENTS())
{
var values = objTypes.Select(s => s.Value).ToArray();
List<DL.PRODUCTS> products =
(from a in db.PRODUCTS
where (description == null || description == "" || a.DESCRIPTION.Contains(description)) &&
(active == null || active == "" || a.ACTIVE.Equals(active, StringComparison.CurrentCultureIgnoreCase)) &&
(mID == null || mID == "" || a.MEDIA_ID == mID) &&
(mID == null || values.Contains(a.OBJECTS))
select a).ToList<DL.PRODUCTS>();
return products;
}
That will generate SQL IN clause.
Note - you can use lambda syntax to compose query by adding filters based on some conditions:
var products = db.PRODUCTS;
if (!String.IsNullOrEmpty(description))
products = products.Where(p => p.DESCRIPTION.Contains(description));
if (!String.IsNullOrEmpty(active))
products = products.Where(p => p.ACTIVE.Equals(active, StringComparison.CurrentCultureIgnoreCase)));
if (!String.IsNullOrEmpty(mID))
products = products.Where(p => p.MEDIA_ID == mID);
if (mID != null)
products = products.Where(p => values.Contains(p.OBJECTS));
return products.ToList();
Linq isn't able to convert the predicate on ListItem to something useful to Sql.
I would suggest that you pre-project the values of the ListItems into a simple List<string> before using this with Contains (which is converted to IN)
var listValues = objTypes.Select(_ => _.Value).ToList();
List<DL.PRODUCTS> products = ...
listValues.Contains(a.OBJECTS))

How to structure a count query that includes children

I have a hierarchy of message types: Request which can contain Offers, which can contain Dialogs. I'm trying to query the database to determine how many of each chain contains a message that has not been read by a given User.
Here's the working query in SQL (but I'd like to be able to do it in a LINQ to Entities query, if possible):
SELECT COUNT(msgID)
FROM tblMessage
WHERE msgTypeID = 1 // Request type
AND msgUserID = 7 // The creator of the Request
AND ( msgWhenRead IS NULL // That they didn't read the top Request, OR has any Offers, etc that haven't been read
OR 0 < ( SELECT COUNT(msgID)
FROM tblMessage
WHERE msgTypeID = 2
AND msgRecipientID = 7 // Looking for Recipient here, as the creator is the person who is making the offer, but the Recipient is being set to the person who made the parent Request.
AND ( msgWhenRead IS NULL
OR 0 < ( SELECT COUNT(msgID)
FROM tblMessage
WHERE msgTypeID = 3 // Is a Dialog
AND msgRecipientID = 7 // Same deal with the Recipient here as with Offers.
AND msgWhenRead IS NULL
)
)
)
)
This is my attempt that is not working with EntityFramework:
response.Requests = repository.Messages
.OfType<Request>()
.Where(r => r.Creator.Id == request.UserId &&
r.dbIsDeleted == "N" &&
r.dbStatusId != (int)RequestStatus.Inappropriate &&
( r.WhenRead == null ||
r.Offers.Select(o => o.RecipientId == request.UserId &&
o.dbIsDeleted == "N" &&
o.dbStatusId != (int)OfferStatus.Inappropriate &&
( o.WhenRead == null ||
o.Dialogs.Select(d => d.RecipientId == request.UserId &&
d.dbIsDeleted == "N" &&
d.dbStatusId != (int)DialogStatus.Inappropriate &&
d.WhenRead == null)
.Any()
))
.Any()
))
.Count();
I tried changing to SelectMany at both r.Offers.Select() and o.Dialogs.Select(), but was getting compiler errors. I was thinking perhaps that was the issue.
What I'm getting right now is that with everything having been read, the Entity Framework query is still finding the top Request, and I'm not sure why. The structure of the EF SQL that gets generated isn't close to that of the one I wrote myself. I can provide the EF SQL if people think that may help.

Categories