Run if condition if data not exists - c#

Please check code bellow. I am having wrong entity query i think. check inside second if condition and marked entity query. My goal is save data if this CategoryID not available. But when i run it on debug i can see simply the if condition being skipped however my database not has any data so it should be empty and run if inside codes. I think i am doing something wrong with entity query which marked bellow. Any idea?
ctx.Level1Cats.Any(x => x.Level1CatId != item.CategoryID.ToString())
foreach (CategoryType item in categories)
{
if (item.CategoryLevel == 1)
{
if (ctx.Level1Cats.Any(x => x.Level1CatId != item.CategoryID.ToString()))
{
CatLevel1.Level1CatId = item.CategoryID;
CatLevel1.Name = item.CategoryName;
ctx.Level1Cats.Add(CatLevel1);
//ctx.SaveChanges();
}
else if (ctx.Level1Cats.Any(x => x.Level1CatId == item.CategoryID.ToString()))
{
CatLevel1.Level1CatId = item.CategoryID;
CatLevel1.Name = item.CategoryName;
ctx.Entry(CatLevel1).State = EntityState.Modified;
ctx.SaveChanges();
}
}
}

To solve your problem using your existing code, you can use All inside of the if and then just use a standard else without the additional check:
if (ctx.Level1Cats.All(x => x.Level1CatId != item.CategoryID.ToString()))
{
...
}
else
{
...
}
This will go into your if block if item.CategoryID does not exist (note that All returns true if the list itself is empty). Otherwise, your else will be used instead.
Another option would be to keep the Any but invert the logic:
if (ctx.Level1Cats.Any(x => x.Level1CatId == item.CategoryID.ToString()))
{
// UPDATE.
}
else
{
// ADD.
}
In this case, if any of the items matches the item.CategoryID, you will peform your update. Otherwise, it'll be the Add.
In my experience, the second option shown is more common, where you're looking specifically to find the item of interest and then reacting accordingly.

Related

check if item contain in list

I have a list of installed programs
With Debug.writeLine I can see in the output that there is a discord item.
result.PackageName It can be Discrod, Discord PTB or Discord Canary.
foreach (var installedItem in _installedApps)
{
if (installedItem.DisplayName.Contains("Discord"))
{
Debug.WriteLine(installedItem.DisplayName);
Debug.WriteLine(result.PackageName);
}
if (installedItem.DisplayName.Trim().Contains(result.PackageName.Trim()))
{
isInstalled = true;
}
else
{
isInstalled = false;
}
}
But the code does not work and always returns false
UPDATE:
If I use the following code
var installedStatus = _installedApps.Where(x => x.DisplayName != null && result.PackageName != null && x.DisplayName.Contains(result.PackageName, StringComparison.OrdinalIgnoreCase)).Any();
And in the list of _installedApps, there is only one item named Discord PTB And also in the loop, which is the PackageName Discrod, Discrod PTB or Discrod Canary.
I have a false report that both versions are installed Only PTB should have an installation report.
But if I use the following code
var installedStatus = _installedApps.Where(x => x.DisplayName != null && result.PackageName != null && result.PackageName.Contains(x.DisplayName, StringComparison.OrdinalIgnoreCase)).Select(x => x.Version);
I have the correct report, but the problem is that other programs are not detected
This is not working because isInstalled is getting set by ever iteration.
So the last installedItem can set the value to false.
in essence this is isInstalled is only relevant to the last item.
If you want to use this code just remove the else.
if you want to use linq i would do it like this
isInstalled = _installedApps.Any(i=>i.DisplayName.Trim().Contains(result.PackageName.Trim()))

Does EntityFramework Monitor variables prior to it's declaration and use?

I couldn't understand what was happening when I use Linq.Any() method to check if object contains a specific value, the code throws a NullReferenceException on variable with data prior it's use.
The code below:
public ML.Order FetchOrder(ML.MLDBContext db, long OrderID)
{
if (db == null)
db = new ML.MLDBContext();
//avoided code to fetch the Order details from another system via API
Order apiOrder = api.OrdersGet(OrderID);
//avoided code to test null results
bool isNew = false; //to check if fetched order is new or must be updated on DB
//load from DB
ML.Order dbOrder = db.Orders.Where(o => o.OrderID == apiOrder.id).FirstOrDefault();
if (dbOrder == null)
{
isNew = true;
//avoided code to fill dbOrder with apiOrder data
//Below code check if user bought the same product before
//the error is thrown here but it's not null
string ListingID = apiOrder.order_items.First().item.id;
var previousOrders = db.Orders.Where(order => order.OrderID != apiOrder.id && order.CustomerID == apiOrder.buyer.id && order.SellerID == apiOrder.seller.id).ToList();
foreach (ML.Order prevOrder in previousOrders)
{
if (prevOrder.OrderedItems.Any(i => i.ListingID == ListingID)) //Line who causes the error
{
//code to mask as reordered item
}
}
Some points:
I'm sure "apiOrder.order_items.First().item.id" always have any value.
I'm sure the Order contains the item I'm looking for and the field isn't nullable.
When I comment the line who causes the error, the debug will pass through without errors
To solve this problem, I had to replace Linq.Any() by foreach
foreach (ML.Order prevOrder in previousOrders)
{
foreach (ML.OrderedItem item in prevOrder.OrderedItems)
{
if (item.ListingID == ListingID)
{
//code to mask as reordered item
}
}
}
My doubt is:
Does Linq.Any() or EntityFramework Monitor variables prior to it's declaration and use?
Why the NullreferenceException was trowed on variable prior it usage?
What's the problem using the Linq.Any() method to check the existence of a value inside EF object?

Newbie performance issue with foreach ...need advice

This section simply reads from an excel spreadsheet. This part works fine with no performance issues.
IEnumerable<ImportViewModel> so=data.Select(row=>new ImportViewModel{
PersonId=(row.Field<string>("person_id")),
ValidationResult = ""
}).ToList();
Before I pass to a View I want to set ValidationResult so I have this piece of code. If I comment this out the model is passed to the view quickly. When I use the foreach it will take over a minute. If I hardcode a value for item.PersonId then it runs quickly. I know I'm doing something wrong, just not sure where to start and what the best practice is that I should be following.
foreach (var item in so)
{
if (db.Entity.Any(w => w.ID == item.PersonId))
{
item.ValidationResult = "Successful";
}
else
{
item.ValidationResult = "Error: ";
}
}
return View(so.ToList());
You are now performing a database call per item in your list. This is really hard on your database and thus your performance. Try to itterate trough your excel result, gather all users and select them in one query. Make a list from this query result (else the query call is performed every time you access the list). Then perform a match between the result list and your excel.
You need to do something like this :
var ids = so.Select(i=>i.PersonId).Distinct().ToList();
// Hitting Database just for this time to get all Users Ids
var usersIds = db.Entity.Where(u=>ids.Contains(u.ID)).Select(u=>u.ID).ToList();
foreach (var item in so)
{
if (usersIds.Contains(item.PersonId))
{
item.ValidationResult = "Successful";
}
else
{
item.ValidationResult = "Error: ";
}
}
return View(so.ToList());

Do not find DeleteOnSubmit method

Im want to delete rows from a table that in my data base.
i have the member
private static WeightScaleEntities Weight = new Weight();
this member contains my database. in the data base i have table: User_Activity.
I want to delete rows from user activity by given i_UserActivityId, as follow:
//Get the rows for delete
var deleteUserActivities = from details in Weight.User_Activity
where details.Id == i_UserActivityId
select details;
Now i want to delete this rows, so i tried to do:
foreach (var item in deleteUserActivities)
{
m_WeightScaleEntities.User_Activity.*
}
and i dont get the method DeleteOnSubmit!
Why?
there is another option???
User_Activity.*: is that a typo?
What I think you want is:
foreach (var item in deleteUserActivities)
{
Weight.DeleteObject(item);
}
And then SaveChanges() on the object context.
BTW, a static object context is not a good idea. You should carefully control the life cycle of object contexts.
There is more than one way to execute deletion in Entity Framework,
You must take into account what are the values that you want to delete? one Row or more.
when you need to delete on Row from table we can use these ways:
// first way
using (WeightScaleEntities db = new WeightScaleEntities())
{
var deleteUserActivities = from details in db.User_Activity
where details.Id == i_UserActivityId
select details;
if (deleteUserActivities.Count() > 0)
{
db.deleteUserActivities.Remove(deleteUserActivities.First());
db.SaveChanges();
}
}
this line deleteUserActivities.Count()>0 to check if you have result in the Query or not.
and this deleteUserActivities.First() if the query return set of rows delete the first. "to make the process more secure if you don't know about the data in the table"
// second way
using (WeightScaleEntities db = new WeightScaleEntities())
{
var deleteUserActivities = (from details in db.User_Activity
where details.Id == i_UserActivityId
select details).SingleOrDefault();
if (deleteUserActivities != null)
{
db.User_Activity.Remove(deleteUserActivities);
// or use this line
//db.Entry(deleteUserActivities).State = System.Data.Entity.EntityState.Deleted;
db.SaveChanges();
}
}
You can also use Single or SingleOrDefault to get a single object. Single or SingleOrDefault will throw an exception, if the result contains more than one element. Use Single or SingleOrDefault where you are sure that the result would contain only one element. If the result has multiple elements then there must be some problem.
Also, if you need to remove one or multi rows use this way:
using (WeightScaleEntities db = new WeightScaleEntities())
{
var deleteUserActivities = (from details in db.User_Activity
where details.Id == i_UserActivityId
select details).ToList<User_Activity>(); //<User_Activity> her name of your DbSet
foreach(deleteObject in deleteUserActivities)
{
db.Entry(deleteObject).State = System.Data.Entity.EntityState.Deleted;
}
db.SaveChanges();
}
Best Regards
and sorry about English language.
using(WeightScaleEntities db=new WeightScaleEntities())
{
var deleteUserActivities = from details in db.User_Activity
where details.Id == i_UserActivityId
select details;
if (deleteUserActivities.Count()>0)
{
db.deleteUserActivities.Remove(deleteUserActivities.First());
db.SaveChanges();
}
}

How to update records from an IList in a Foreach loop?

My controller is passing through a list which I then need to loop through and update every record in the list in my database. I'm using ASP.NET MVC with a repository pattern using Linq to Sql. The code below is my save method which needs to add a record to an invoice table and then update the applicable jobs in the job table from the db.
public void SaveInvoice(Invoice invoice, IList<InvoiceJob> invoiceJobs)
{
invoiceTable.InsertOnSubmit(invoice);
invoiceTable.Context.SubmitChanges();
foreach (InvoiceJob j in invoiceJobs)
{
var jobUpdate = invoiceJobTable.Where(x => x.JobID == j.JobID).Single();
jobUpdate.InvoiceRef = invoice.InvoiceID.ToString();
invoiceJobTable.GetOriginalEntityState(jobUpdate);
invoiceJobTable.Context.Refresh(RefreshMode.KeepCurrentValues, jobUpdate);
invoiceJobTable.Context.SubmitChanges();
}
}
**I've stripped the code down to just the problem area.
This code doesn't work and no job records are updated, but the invoice table is updated fine. No errors are thrown and the invoiceJobs IList is definitely not null. If I change the code by removing the foreach loop and manually specifying which JobId to update, it works fine. The below works:
public void SaveInvoice(Invoice invoice, IList<InvoiceJob> invoiceJobs)
{
invoiceTable.InsertOnSubmit(invoice);
invoiceTable.Context.SubmitChanges();
var jobUpdate = invoiceJobTable.Where(x => x.JobID == 10000).Single();
jobUpdate.InvoiceRef = invoice.InvoiceID.ToString();
invoiceJobTable.GetOriginalEntityState(jobUpdate);
invoiceJobTable.Context.Refresh(RefreshMode.KeepCurrentValues, jobUpdate);
invoiceJobTable.Context.SubmitChanges();
}
I just can't get the foreach loop to work at all. Does anyone have any idea what I'm doing wrong here?
It seems like the mostly likely cause of this problem is that the invokeJobs collection is an empty collection. That is it has no elements hence the foreach loop effectively does nothing.
You can verify this by adding the following to the top of the method (just for debugging purposes)
if (invoiceJobs.Count == 0) {
throw new ArgumentException("It's an empty list");
}
Change this
var jobUpdate = invoiceJobTable.Where(x => x.JobID == 10000).Single();
jobUpdate.InvoiceRef = invoice.InvoiceID.ToString();
invoiceJobTable.GetOriginalEntityState(jobUpdate);
invoiceJobTable.Context.Refresh(RefreshMode.KeepCurrentValues, jobUpdate);
invoiceJobTable.Context.SubmitChanges();
to
var jobUpdate = invoiceJobTable.Where(x => x.JobID == 10000).Single();
jobUpdate.InvoiceRef = invoice.InvoiceID.ToString();
invoiceJobTable.SubmitChanges();
It looks like your GetOriginalEntityState doesn't actually do anything, because you don't use the returned value. I can't see any reason why you are making the DataContext.Refresh() call. All it does is erase the changes you made, thus making your "foreach loop not work"

Categories

Resources