avoid Row not found or changed error - c#

I have banners on a site. When banner showed then I increment field in DB.
This is code:
public Banner GetBanner(CategoryBanner type)
{
var banners = Database.Banners.Where(b => b.IsPublish.Value &&
b.Category.Value == (int)type &&
b.PeriodShowCountAlready < b.PeriodShowCount || b.IsPublish.Value && b.Category.Value == (int)type &&
b.ShowNext < DateTime.Now);
var count = banners.Count();
if (count != 0)
{
var skip = new Random().Next(banners.Count() - 1);
Banner banner = banners.Skip(skip).FirstOrDefault();
if (banner != null)
{
UpdatePeriodShowCountAlready(banner); // problem is inside this method
if (banner.ShowStart == null)
UpdateShowStartAndEnd(banner);
return banner;
}
}
return null;
}
private void UpdatePeriodShowCountAlready(Banner banner)
{
try
{
if (banner != null)
{
banner.PeriodShowCountAlready++;
if (banner.PeriodShowCountAlready >= banner.PeriodShowCount && banner.ShowNext < DateTime.Now)
{
banner.PeriodShowCountAlready = 0;
banner.ShowStart = null;
banner.ShowNext = null;
}
Database.SubmitChanges();
}
}
catch (Exception ex)
{
ErrorLog.GetDefault(null).Log(new Error(ex));
}
}
And, I get the following error:
System.Data.Linq.ChangeConflictException
Row not found or changed.
This error is simple to reproduce:hold down the F5 is enough for a few seconds.
I understand why this error is occur, but how to rewrite my code properly?
Thanks.

Related

Getting System.StackOverflowException , in a recursive function call?

I have to two function which is used to find tags inside the tags like, there is a tag A=B(C(D(E))) so i have to find all the tags inside B then all the tags inside C and so on. I write two function but getting the error System.StackOverflowException. In the first function i am providing the tag ID and against that tag id i am getting getNestesCalTagsId and then calling the getNestedCalTagsIngredients() function. But when there are lot of recursion calls i get the error System.StackOverflowException. Below is my whole code.
public List<int?> getNestedCalTags(int? calTagId)
{
var getNestesCalTagsId = db.Dependencies_Metrix.Where(x => x.Cal_Tag_P_Id == calTagId && x.Status == true && x.Cal_Tag_Id_FK!=null).Select(x => x.Cal_Tag_Id_FK).ToList();
if (getNestesCalTagsId.Count > 0)
{
nestedCalFTags.AddRange(getNestesCalTagsId);
foreach (var item in getNestesCalTagsId)
{
if (item != null)
{
getNestedCalTagsIngredients(item.Value);
}
}
}
if (nestedCalFTags.Count > 0)
{
int countedTags = nestedCalFTags.Count;
List<int?> tags = new List<int?>(nestedCalFTags);
for (int i = 0; i < tags.Count; i++)
{
if (tags[i] != null)
{
getNestedCalTagsIngredients(tags[i].Value);
}
}
}
return nestedRawTags;
}
public bool getNestedCalTagsIngredients(int nestCalTagId)
{
var getCalTags = db.Dependencies_Metrix.Where(x => x.Cal_Tag_P_Id == nestCalTagId && x.Status == true).ToList();
if (getCalTags.Count > 0)
{
foreach (var item in getCalTags)
{
if (item.Cal_Tag_Id_FK != null)
{
var getNestedCalTagParent = db.Dependencies_Metrix.Where(x => x.Cal_Tag_P_Id == item.Cal_Tag_Id_FK && x.Status == true && x.Cal_Tag_Id_FK!=null).Select(x => x.Cal_Tag_Id_FK).ToList();
if (getNestedCalTagParent != null)
{
nestedCalFTags.AddRange(getNestedCalTagParent);
getNestedCalTags(item.Cal_Tag_Id_FK);
}
}
else
{
var rawTagId = db.Dependencies_Metrix.Where(x => x.Cal_Tag_P_Id == item.Cal_Tag_P_Id && x.Real_Tag_Id_FK!=null).Select(x => x.Real_Tag_Id_FK).ToList();
if (rawTagId != null)
{
foreach (var rawItem in rawTagId)
{
if (rawItem!=null)
{
if (nestedRawTags.IndexOf(rawItem.Value) == -1)
{
nestedRawTags.Add(rawItem.Value);
}
}
}
}
nestedCalFTags.Remove(nestCalTagId);
}
}
}
return true;
}

ICollectionView multiple filter

So I have a fitler TextBox where I want to search for different type of docs in a grid the code where I have different type of columns such as: Date,DocId,ClientId.
For a search I write on a filter Textbox something like that DocId:2002 and It just work fine but when I try to make a multiple search for example DocId:2002 ClientId:201 It doesnt search because of the return it just does an infinite loop.
private void TextBoxFilter_TextChanged(object sender, TextChangedEventArgs e)
{
foreach (Match m in Regex.Matches((sender as TextBox).Text, pattern, options))
{
if (m.Value != "")
{
Func<String, String> untilSlash = (s) => { return filters[re.Match(s).Groups[1].ToString()] = re.Match(s).Groups[2].ToString(); };
untilSlash(m.Value);
}
}
ICollectionView cv = CollectionViewSource.GetDefaultView(this.DataGridDocList.ItemsSource);
if (filters.Count == 0)
{
cv.Filter = null;
}
else
{
cv.Filter = o =>
{
for (int i = 0; i < filters.Count; i++)
{
if (filters.ElementAt(i).Key == "Date")
{
if (DateVerify.Match(filters.ElementAt(i).Value).Success)
{
return (o as Document).DateCreated < Convert.ToDateTime(DateVerify.Match(filters.ElementAt(i).Value).Groups[1].ToString()) && (o as Document).DateCreated > Convert.ToDateTime(DateVerify.Match(filters.ElementAt(i).Value).Groups[2].ToString());
}
else
{
var dateString = (o as Document).DateCreated.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture);
return dateString.Contains(DateVerify.Match(filters.ElementAt(i).Value).Groups[1].ToString());
}
}
if (filters.ElementAt(i).Key == "DocId")
{
return (o as Document).DocumentId.ToString().Contains(filters.ElementAt(i).Value);
}
if (filters.ElementAt(i).Key == "ClientId")
{
return (o as Document).ClientId.ToUpper().Contains(filters.ElementAt(i).Value.ToUpper());
}
}
return false;
};
filters.Clear();
}
}
So my question is how can I do an big search with all the filters at one time?
Manually I can add them 1 by 1 and it will be something like search1 && search2 && search3 but It will take too much time and It's probably not the best solution
There are many ways of building up the predicate. However my suggestion is to keep it simple and just create one method that returns true or false. It's good practice to only return once in a method.
The code below if for illustration purposes (as I'm unable to test it):
ICollectionView cv = CollectionViewSource.GetDefaultView(this.DataGridDocList.ItemsSource);
if (filters.Any())
{
cv.Filter = new Predicate<object>(PredicateFilter);
}
else
{
cv.Filter = null;
}
Then Predicate method to filter results:
public bool PredicateFilter(object docObj)
{
Document doc = docObj as Document;
var response = new List<bool>();
for (int i = 0; i < filters.Count; i++)
{
if (filters.ElementAt(i).Key == "Date")
{
if (DateVerify.Match(filters.ElementAt(i).Value).Success)
{
response.Add(doc.DateCreated < Convert.ToDateTime(DateVerify.Match(filters.ElementAt(i).Value).Groups[1].ToString()) && doc.DateCreated > Convert.ToDateTime(DateVerify.Match(filters.ElementAt(i).Value).Groups[2].ToString()));
}
else
{
var dateString = doc.DateCreated.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture);
response.Add(dateString.Contains(DateVerify.Match(filters.ElementAt(i).Value).Groups[1].ToString()));
}
}
else if (filters.ElementAt(i).Key == "DocId")
{
response.Add(doc.DocumentId.ToString().Contains(filters.ElementAt(i).Value));
}
else if (filters.ElementAt(i).Key == "ClientId")
{
response.Add(doc.ClientId.ToUpper().Contains(filters.ElementAt(i).Value.ToUpper()));
}
}
return response.All(m => m); // if all filters came back with true, return 1 response of true else false.
}

Return error message from a void method in C#

I'm currently trying to get my method to return an error message if a condition isn't valid. But I am uncertain how to go about this in a void method.
I have a method that looks like this
[HttpPost]
[ValidateAntiForgeryToken]
[Audit]
public void AddUnits(int so_id, int site_id, int[] addItem_id, int[] addItem_qty, int[] addItem_disc)
{
// Loop however many times is necessary to iterate through the largest array
for (int i = 0; i < Math.Max(Math.Max(addItem_id.Length, addComp_id.Length), addPart_id.Length); i++)
{
foreach (SODetails sod in db.SalesOrders.Find(so_id).SalesDetails)
{
if (i < addItem_id.Length && addItem_qty[i] != 0 && sod.ItemID == addItem_id[i] && addItem_id[i] != 365 && addItem_id[i] != 410)
{
sod.item_qty += addItem_qty[i];
sod.item_discount = addItem_disc[i];
addItem_id[i] = 0;
addItem_qty[i] = 0;
addItem_disc[i] = 0;
}
}
db.SaveChanges();
if(i < addItem_qty.Length && addItem_qty[i] != 0)
{
SODetails sODetails = new SODetails
{
SalesOrderID = so_id,
SiteID = site_id
};
// Only add a unit to the SODetails object if it's not null and has an id and quanitity specified
if(i < addItem_id.Length && addItem_id[i] != 0 && addItem_qty[i] != 0)
{
sODetails.ItemID = addItem_id[i];
sODetails.item_qty = addItem_qty[i];
sODetails.item_discount = addItem_disc[i];
}
if (sODetails.SiteID == 0)
sODetails.SiteID = null;
SalesOrder SO = db.SalesOrders.Find(sODetails.SalesOrderID);
SODetails salesOrderDetails = db.SODetails.Add(sODetails);
salesOrderDetails.SalesOrder = SO;
Item SO_Item = db.Items.Find(sODetails.ItemID);
Component SO_Component = db.Components.Find(sODetails.ComponentID);
Part SO_Part = db.Parts.Find(sODetails.PartID);
if (SO_Item != null)
{
if (SO.OrderType == SOType.OffSiteInventory && sODetails.InventorySite == "Main Inventory" && SO_Item.On_Hand < salesOrderDetails.item_qty)
{
ModelState.AddModelError(string.Empty, "Not enough stock in inventory");
//TempData["SalesOrderMessage"] = SO_Item.SalesOrderMessage;
}
sODetails.item_qty = sODetails.item_qty == null ? 0 : sODetails.item_qty;
int qtyOrdered = sODetails.item_qty == null ? 0 : (int)sODetails.item_qty;
salesOrderDetails.dynamicItem_qty = qtyOrdered;
if (SO_Item.SalesOrderMessage != null)
TempData["SalesOrderMessage"] = SO_Item.SalesOrderMessage;
}
db.SODetails.Add(sODetails);
}
}
db.SaveChanges();
}
Here is the part of the code where I am doing the validation check
if (SO.OrderType == SOType.OffSiteInventory && sODetails.InventorySite == "Main Inventory" && SO_Item.On_Hand < salesOrderDetails.item_qty)
{
ModelState.AddModelError(string.Empty, "Not enough stock in inventory");
//TempData["SalesOrderMessage"] = SO_Item.SalesOrderMessage;
}
If the condition is valid I want it to return to the screen with an error message showing up. But with the method being Void, I don't know how I can make it do this, or I don't know if it is even possible.
You could create a specific exception class that you can throw in your void function. You then handle this exception in the calling function.
class NotEnoughStockException : Exception {}
Then in your method:
If no stock ...
throw new NotEnoughStockException();
In the calling method
try {
call the stock method
} catch NotEnoughStockException {
whatever you want to do
}
Create a wrapper function that will call your stock function. You do try catch in that new function and return an error message. Your Ajax should call the new function.

Linq to object freezing

I have some LINQ to Object Query Code:
List<ePayDocumentOperation> additionalDocuments = new List<ePayDocumentOperation>();
try
{
additionalDocuments = (from op in possibleClientDocuments
let senderAccountID = GetSenderAccountID(con, op)
where Filter.Wallets.Contains(senderAccountID)
select op).ToList();
}
catch (Exception ex)
{
// some catcher
}
possibleClientDocuments object contains about 3 000 records. Not so much but the query freeze and I don't get result. I don't get any execeptions. I try to select code to try catch block but I don't see any exceptions and at the same time I don't get result too.
How to check the problem of query and why I don't getting result?
Thanks!
P.S.
private static long GetSenderAccountID(LavaPayEntities Con, ePayDocumentOperation operation)
{
long result = default(long);
// Payment
if (operation.OperationPatternID == Chart.Operations.PS_Payment)
{
var ipnRequest = Con.eIPNRequests.FirstOrDefault(ir => ir.OperationID == operation.ID);
if (ipnRequest == null) return result;
if (ipnRequest.ClientAccountID != null && ipnRequest.ClientAccountID != 0) return (long)ipnRequest.ClientAccountID;
var clientAccount = Con.eAccounts.FirstOrDefault(a => a.Email.Email == ipnRequest.ClientEmail);
if (clientAccount != null)
{
result = clientAccount.ID;
}
else
{
var client = ipnRequest.Client;
if (client != null)
{
clientAccount = client.Accounts.FirstOrDefault();
if (clientAccount != null)
{
result = clientAccount.ID;
}
}
}
}
// Other Operations
else
{
result = operation.SenderAccountID.HasValue ? operation.SenderAccountID.Value : 0;
}
return result;
}

Getting NullReferenceException don't know why

I wasn't the one who coded this line of code, and I can't gt to understand whoever did it, why did this way on this line: res.Data.Find(itm => itm.Meta.ID.ToUpper() == i["MetaDataID"].ToString().ToUpper()).Value[i["LocaleID"].ToString()] = i["Value"].ToString();
And this line gives me a NullReferenceException. How can I get around it?
public static void LoadData(Value.Item _res)
{
DataTable Res = Connector.Run("SELECT * FROM Data WHERE ItemID='" + _res.ID + "'");
if (Res.Rows.Count != 0)
{
foreach (DataRow i in Res.Rows)
{
try
{
_res.Data.Find(itm => itm.Meta.ID.ToUpper() == i["MetaDataID"].ToString().ToUpper()).Value[i["LocaleID"].ToString()] = i["Value"].ToString();
}
catch (Exception)
{
_res.Data.Add(new Value.Data(
i["ID"].ToString(),
i["Value"].ToString(),
i["LocaleID"].ToString(),
i["MetaDataID"].ToString()
));
}
}
}
}
Thx a lot guys!!! Here is my working solution which hrows no Exceptions anymore!
public static void LoadData(Value.Item _res)
{
DataTable Res = Connector.Run("SELECT * FROM Data WHERE ItemID='" + _res.ID + "'");
if (Res.Rows.Count != 0)
{
foreach (DataRow i in Res.Rows)
{
bool _flagged = false;
var _result = _res.Data.Find(itm => itm.Meta.ID.ToUpper() == i["MetaDataID"].ToString().ToUpper());
if(_result != null && i["LocaleID"] != null)
{
if (i["Value"] == null || i["LocaleID"] == null || i["MetaDataID"] == null)
_flagged = true;
}
else
{
_flagged = true;
}
if (_flagged)
{
_res.Data.Add(new Value.Data(
i["ID"].ToString(),
i["Value"].ToString(),
i["LocaleID"].ToString(),
i["MetaDataID"].ToString()
));
}
//try
//{
// _res.Data.Find(itm => itm.Meta.ID.ToUpper() == i["MetaDataID"].ToString().ToUpper()).Value[i["LocaleID"].ToString()] = i["Value"].ToString();
//}
//catch (Exception)
//{
// _res.Data.Add(new Value.Data(
// i["ID"].ToString(),
// i["Value"].ToString(),
// i["LocaleID"].ToString(),
// i["MetaDataID"].ToString()
// ));
//}
}
}
}
Impossible to answer accurately without having the code under the debugger, however what is certain is that at least one of the following has a value of null:
_res.Data
itm.Meta
itm.Meta.ID
i["MetaDataID"]
i["LocaleID"]
i["Value"]
Old-skool debugging:
Break the statement down to it's consituent parts - using local variables. Step-through and find which one is null.
Check if one of the following are null:
i["MetaDataID"]
i["LocaleID"]
i["Value"]

Categories