I would like to ask for your help. I want to validate my delete request class. The rule is:
"Deletion allowed only for one element with the biggest price in
database for each type of product"
. repositoryEntities is not null but the Result is: Enumeration yielded no results.
Can you please check below code and let me know what is wrong?
private void CanIDelete(DeleteProductRequest entity, CustomContext context)
{
var repositoryEntities = _productRepository.Queryable.Where(s => s.TypeOfProductId.Equals(entity.TypeOfProductId) && !s.IsDeleted);
if (repositoryEntities != null)
{
var theBiggestPriceInDatabase = Decimal.MinValue;
foreach (var repositoryEntity in repositoryEntities)
{
if (theBiggestPriceInDatabase < repositoryEntity.Price)
{
theBiggestPriceInDatabase = repositoryEntity.Price;
continue;
}
if (entity.Price != theBiggestPriceInDatabase)
{
context.AddFailure("Deletion allowed only for one product 'with the biggest price' in database for each type of product");
return;
}
}
}
Related
I have this Service that works to delete one (1) row from the database (Sorry for any lingo errors.):
public bool DeleteSchedulesFromDate(DateTime objDateTime)
{
var result = _db.Schedules.FirstOrDefault(x => x.AppointmentDateEnd <= objDateTime);
if (result != null)
{
_db.Schedules.Remove(result);
_db.SaveChanges();
}
else
{
return false;
}
return true;
}
This as the calling function:
private void DeleteSchedules(string dtEnd)
{
deleteScheduleDate = dtEnd;
DateTime _dtEnd;
if (DateTime.TryParse(dtEnd, out _dtEnd))
{
var result = #Service.DeleteSchedulesFromDate(_dtEnd);
schedules.Clear();
schedules = Service.GetSchedules();
if (result)
{
this.ShouldRender();
}
}
}
But how do I change it to delete all rows that matches the passed DateTime object?
I have tried :
to change it to a List, but then the bool doesn't work.
set a loop in the Service, but can't make it run correctly.
set a loop in the function call, but can't make it work either.
to google and look up other posts on SO, but found no match.
Instead of searching for the first match with FirstOrDefault you should get all valid result into a List (Where + ToList) and delete all of them (RemoveRange)
var result = _db.Schedules.Where(x => x.AppointmentDateEnd <= objDateTime).ToList();
if (result.Any())
{
_db.Schedules.RemoveRange(result);
_db.SaveChanges();
}
Let me explain my matching problem with a real example (the problem is generic). Assume having 2 lists: of "selections" loaded from different sources. The list don't have duplicates.
Let's say mkTPL.Selections and mkDB.Selections come from SQL Tables each with an unique index on the id and the selection's name. The problem is that sometimes IdSelectionType is null (in the selection from mkTPL.Selections)
foreach (var selTPL in mkTPL.Selections)
{
foreach (var selDB in mkDB.Selections)
{
if (selTPL.IsTheSame(selDB))
selTPL.OddOrResultValue = selDB.OddOrResultValue;
}
}
public bool IsStessaSelezione(SelectionPrints selDb)
{
if (selDb.IdSelectionType == this.IdSelectionType)
return true;
else
{
bool isSameName = selDb.Name == this.Name;
bool isSimilarName = false;
if (!isSameName)
{
isSimilarName = RegexReplace(selDb.Name, #"\([\d.]+\)") == RegexReplace(this.Name, #"\([\d.]+\)");
}
return isSameName || isSimilarName;
}
}
The match alghtoritm that I have implemented is not efficient. Once a selection is matched I shouldn't try to match it further with others (because of the unique index on the id and on the selection name).
Linq could provide me an easy solution?
First of all, you should break when you found a match:
foreach (var selTPL in mkTPL.Selections)
{
foreach (var selDB in mkDB.Selections)
{
if (selTPL.IsTheSame(selDB))
{
selTPL.OddOrResultValue = selDB.OddOrResultValue;
break; // <--
}
}
}
Second, I would make a dictionary of mkDB.Selections, where you store the regexed value so you don't have to make that calculation over and over again, on every iteration.
Something like:
var mkDBDictionary = mkDB.Selections.ToDictionary(s => RegexReplace(s.Name, #"\([\d.]+\)"), s => s);
foreach (var selTPL in mkTPL.Selections)
{
string selTPLName = RegexReplace(selTPL.Name, #"\([\d.]+\)");
if (mkDBDictionary.TryGetValue(selTPLName, out var selDB))
{
selTPL.OddOrResultValue = selDB.OddOrResultValue;
}
}
I have a DB with no constraints (given, not changeable). My model look like
public MyModel
{
public long Id { get; set; }
// Even if database column 'Value' could be NULL,
// the model - from business view - could not.
public long Value { get; set; }
}
My data I'd like to read is
Id Value
1 1
2 2
3 NULL
4 4
When I read with with DBContext.MyModel.ToList() it fails, of course. Is there any possibility to catch the error on 3rd row and return the 3 valid ones?
I don't dependent on EF but I like an automatic mapping between DB an Code.
Update:
It seems I wasn't specific enough. I need the 3 rows AS WELL AS a notification for the error.
Additional I've created a simple case for demo. In real life I have around 800 tables with up to 250 columns. I can't catch anything by model modification like dates out of range, missing relationships and other stuff.
What I really need is a try..catch for every row or an event on row reading failure, something like this.
Ok, solved. Not very elegant, but functional.
var query = _DBContext
.Database
.SqlQuery<MyModel>("SELECT * FROM MyModel");
var result = new List<MyModel>();
var enumerator = query.GetEnumerator();
while (true)
{
try
{
var success = enumerator.MoveNext();
if (!success)
break;
var model = enumerator.Current;
result.Add(model);
}
catch (Exception ex)
{
}
}
return result;
You need to use nullable type
public MyModel
{
public long Id { get; set; }
// Even if database column 'Value' could be NULL,
// the model - from business view - could not.
public long? Value { get; set; }
}
And also, in your select query, you should exlude Value = null
var myModel = models.Where(x => x.Value != null);
Hope it helps.
I'm not entirely sure I understand what you're trying to do, but if you want to get a reflection of what's in the table, then why not make your model match the query? If Value can be NULL, then make Value nullable (i.e. define it as long?).
That way, you can simply do:
var records = DbContext.MyModel.ToList();
If you then want to filter out the NULLs, you can do:
records.Where(r => r.Value.HasValue)
And if you want the ones with NULLs you can do:
records.Where(r => !r.Value.HasValue)
Or if you want to know whether any row had a NULL you could do:
records.Any(r => !r.Value.HasValue)
Use the following code:
var list = from m in DBContext.MyModel
where (m != null)
select m;
And then just convert var list to a List of your choosing.
Edit 1
var myModel = models.Where(x => x.Value != null).ToList();
As kienct89 suggested might also work.
Edit 2
There are multiple options for "catching" the error
If you want to throw an exception just use this:
if(myList.Count() < DBContext.MyModel.Count()){
Exception myException = new Exception("Not all items ware correctly loaded");
throw myException;
}
OR create a seperate array with the faulty ones:
var faultyList = from m in DBContext.MyModel
where (m == null)
select m;
Or:
var faultyList= models.Where(x => x.Value == null).ToList();
So i have a function that gets a list of students from a web service and also query the localdb for all the students in there. the data is placed in two different list. So i want to check to see if a new student already exists in the localdb List. if it does, update it and it if doesn't then add it. i unable to get it working . I am trying to perform this using LINQ, but i can't seem to get it working right. My LINQ skills are amateurish at best.
public async Task GetStudents()
{
String controllerName = "Students";
List<Students> newStudentData = await RunGetAsync<Students>(controllerName);
// get all the service types that already exists in the localStudent Db
List<Students> currentStudentData = db.Studentss.ToList();
foreach (Students existingStudents in currentStudentData)
{
foreach (Students newStudents in newStudentData)
{
IEnumerable<Students> selectStudents = from student in newStudentData // check if Students exist in the database
where student.Id == existingStudents.Id
select student;
if (selectStudents == null) // didn't find it, then add it
{
db.Students.Add(newStudents);
}
if (selectStudents != null) // found it , then update the informations
{
Students updatedStudents = new Students();
foreach (var field in selectStudents)
{
updatedStudents.FName = field.FName;
updatedStudents.LName = field.LName;
updatedStudents.ZipCode = field.ZipCode;
updatedStudents.AccessCode = field.AccessCode;
}
db.Entry(updatedStudents).State = System.Data.Entity.EntityState.Modified;
}
}
}
db.SaveChanges();
}
Thank you very much for your help.
you're looping more than you need :
foreach (Students newStudents in newStudentData)
{
var student = currentStudentData.FirstOrDefault(s => s.Id == newStudents.Id);
if(student == null)
{
//add
}
else
{
//update
}
}
with FirstOrDefault you can find out if it exists and get a reference to it at the same time, if it does.
You could use Intersect and Except like below:
//Find students that already exist to update
var updateStudents = currentStudentData.Intersect(newStudentData);
//Find new students to add
var addStudents = newStudentData.Except(currentStudentData);
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?