I am working on a project, and I have hit a brick wall. My code adds dates with a type to a database, but I need to create an error when there is already a similar entry within the code. However, I cannot get my loop to check for duplicates, and instead it adds duplicates! I am not very good at loops so I'm a bit stuck at this. Any help to check for duplicate entries and to stop it from creating too many would be a great help! Changed my code within this text area so it's not exactly the same variable names.
Here is my code: -
if (DT != null && DT.Length > 0 || DF != null && DF.Length > 0)
{
for (int t = 0; t < Type.Length; t++)
{
DateTime checkDate;
if (Type.IsSelectionValid(8, out typeError) && DateTime.TryParse(DF, out typeError) && DateTime.TryParse(DT, out checkDate))
{
TypeValid = true;
error.Error = false;
}
else
{
error.Errors = "Type-Invalid";
absenceTypeValid = false;
break;
}
}
else
{
error.Errors = "Type-Duplicate";
TypeValid = false;
break;
}
}
}
I'm 'fairly' sure you are going out of your way to make a problem more difficult than it is here, but I can't say for sure since I'm not entirely sure what this is doing.
But here are the conditions that need to be met to get to your Type-Duplicate Error line:
1) Either DT or DF have to not be empty to get past the first if statement
2) Either IsSelectionValid() has to return false or either DT or DF have to be an invalid DateTime.
None of those things constitute a duplicate.
Let me try to explain what I see here:
I first see variables called DT, DF. I can see these are dates, but that's all I know about them. I see 'Type' which I understand even less about than DT and DF. I see that you are doing a loop for Type.Length number of iterations... but what does this mean to me if I don't have a clue what Type is?
If you had comments explaining what things are I 'might' be able to help you, but there's just really not enough information to know what's happening here.
If you simply want to know how to avoid adding duplicates to a database, then I would suggest adding a constraint or index to the column in the database and then you can just catch the exceptions that are thrown when you try to insert a duplicate and deal with it that way. Alternatively, account for it in your insert statement.
Related
So, I'm writing a program that is reads table data and puts cells values in a List. I made it, but there is one problem – UsedRange takes all cells on sheet so there is more items then I need and also, when I specify range by ["A:A", Type.Missng] it gives me an exception:
System.ArgumentException: "HRESULT: 0x80070057 (E_INVALIDARG))"
So my question is how to make it correctly?
Code is:
foreach (Excel.Range row in usedRange)
{
for(int i=0; i<lastCell.Row; i++)
{
if (row.Cells[4, i + 1].Value2 != null)
{
personlist.Add(Convert.ToString(row.Cells[4, i + 1].Value2));
}
else { i++; }
}
foreach(var person in personlist) {
Console.WriteLine(person);
}
}
UPD: I need a last used row, that's why I'm using UsedRange. So if there is any alternatives, like, checking if(!=null)? I will gladly try it
Tried to give it specific range, some tries to made a code like here C# - How do I iterate all the rows in Excel._Worksheet?
and here
https://overcoder.net/q/236542/программно-получить-последнюю-заполненную-строку-excel-с-помощью-c
but maybe I'm a dumb one, 'cause there is literally more than one articles about it and non of it works with me
The problem is 'used range' can include empty range (who knows how excel decides that magic number - if you type a letter on some arbitrary row and then delete it Excel can decide that cell is still part of your used range). You want your own custom definition of what a 'usedRange' is, which presumably is the range of non-blank rows. There's two straightforward ways of implementing this yourself (which gives you added control over it should you want to customize it).
You can just filter the list after the fact removing all blank entries. Or you can process the list in reverse, skipping rows till you find one matching your criteria
bool startProcessing = false;
for(int i=lastCell.Row-1; i>=0; i--)
{
if(!startProcessing){//bool is in case you want blank rows in the middle of the file, otherwise check valid row always
//check if valid row
//continue; if not, set startProcessing to true if yes
}
if (row.Cells[4, i + 1].Value2 != null)
{
personlist.Add(Convert.ToString(row.Cells[4, i + 1].Value2));
}
//else { i++; } //this is a bug, will cause a line skip
}
Also, as an aside - when you call i++; in the body of your for loop, it then calls it again in the header of your for loop and i += 2 skipping a row. Use continue; or just remove the else block altogether.
There's probably a way to get a cellRange matching your criteria, but imo doing it yourself can be better - you can ensure it does exactly what you want.
I have a simple function in my Unity game code where I am looking for a "work spot" - an empty place for my NPCs to do some task.
This code works perfectly well 99.999% of the time, but throws a NULL REFERENCE EXCEPTION very occasionally and I can't for the life of me figure out where. I have tried to catch every possible place where something could be unassigned and can't find it. There must be some edge case I am missing, or something in my code that misbehaves under some strange circumstances.
So my code is flawed and I don't understand where. Help me improve it:
public Transform[] workSpots;
public Transform findAvailableWorkSpot() {
if (workSpots == null || workSpots.Length == 0) return null; // sometimes we have no work spots
int i=0;
while (i<10) {
Transform spot = workSpots[Random.Range(0, workSpots.Length)];
if (spot != null && spot.childCount == 0) {
return spot;
}
i++;
}
// couldn't find one randomly, let's just iterate over them:
foreach (Transform spot in workSpots) {
if (spot != null && spot.childCount == 0) {
return spot;
}
}
Debug.LogError("could not find free workspot on "+gameObject.name);
return null;
}
Logic:
first, try up to 10 times to get a free random work spot. I parent the NPC to the work spot when he is working there, so spot.childCount == 0 is true if the spot has no NPC on it right now.
if that fails, then I just iterate over all of them and pick the first free one.
it is ok to return null here, the calling code will handle that
The Diagnostic backend tells me that 2-4 times a day someone experiences a Null Reference Exception in this function, but diagnostics doesn't tell me the line number and I've never seen it locally. I'm looking at it again and again and I can't spot where it could be. Maybe something more fundamental is wrong with my code?
Additional Information:
workspots is initialized in Awake() and is never again changed, so I am sure that the test at the beginning of the function works and it's not possible that it goes to null while the function is running.
This is not directly an answer to where exactly the exception comes from.
But if you are open to using Linq you can simplyfy your code a lot!
I would simply use
using System.Linq;
...
public Transform[] workSpots;
public bool TryFindAvailableWorkSpot(out Transform freeSpot)
{
// First heck this component even is alive
if (!this || workSpots == null || workSpots.Length == 0)
{
freeSpot = null;
return false;
}
// First "Where" filters out only those spots that exist and have no children
// then "OrderBy" randomizes these results
// then we take the first one or null if there isn't any
freeSpot = workSpots.Where(spot => spot && spot.childCount == 0).OrderBy(spot => Random.value).FirstOrDefault();
// use the implicit bool operator for checking if we have found a valid reference
return freeSpot;
}
and then instead of using
var spot = yourClass.findAvailableWorkSpot();
and having to again check for null and potential exceptions you would rather simply do the check in the same line using e.g.
if(yourClass.TryFindAvailableWorkSpot(out var spot))
{
... Do someting with spot
}
else
{
Debug.LogError("could not find free workspot");
}
See
Linq Where
Linq OrderBy
Random.value
Linq FirstOrDefault
Unityengine.Object implicit bool operator
I don't think you are looking at the right place where the exception happened. The way you've written the code it's just not possible for workSpots to be null or empty.
The only places where I can see a null reference exception happening is if you are trying to access workSpots[index] -> and that returns a Transform object that is null and you try using it (but in your code you are prepared for that).
Maybe the places where you use that particular method do not check if the Transform that you are returning is null before trying to access it.
If your code is well written and you don't believe it then the null reference exception is probably caused by gameObject.name when trying to log an error. If it isn't that then I have no idea honestly.
having an ongoing problem with my project that I'm working on. Fairly new to C# and ASP.Net.
I'm currently trying to get an entry from a textfield and compare it to the last entry in my database. For my business rule, the Reading must not be higher than the Previous Years reading. I will have multiple Readings from different machines.
meterReading is the instance of my class MeterReading
This is currently what I have:
var checkMeterReading = (from p in db.MeterReading
where (p.Reading < meterReading.Reading)
select p);
if (checkMeterReading.Count() > 0)
{
if (!String.IsNullOrEmpty())
{
//saves into DB
}
}
else
{
TempData["Error"] = "Meter Reading must be higher than last actual";
}
Don't know if I'm doing anything stupid or not. Thanks in advance
You're currently checking whether any reading in the database is less than the current reading; that's clearly not right, as you could have stored readings of 200, 5000, 12005 and be testing against 9000. There are 2 readings less than 9000, so your code would allow you to insert the 9000 at the end. What you want to check is that all the readings are less, or equivalently: that no reading is higher:
var higherExists = db.MeterReading.Any(p => p.Reading > newReading);
if(higherExists) {
// danger!
} else {
// do the insert... as long as you're dealing with race conditions :)
}
Note that a better approach IMO would be to compare using time, since errors and meter replacements mean that the readings are not necessarily monotonic. Then you'd do something like:
var lastRow = db.MeterReading.OrderByDescending(p => p.ReadingDate).FirstOrDefault();
if(lastRow == null || lastRow.Reading < newReading) {
// fine
} else {
// danger
}
Note that your current code only supports one customer and meter. You probably also need to filter the table by those.
I'm not sure why this exception is happening... I could understand if I wasn't checking for i < table.Rows.Count but I do check for this, so I am confused as to why the row is not in the table... I've hit a roadblock here and could use someone a little more experienced with this problem than me. I just hope it's one of those small stupid mistakes.
Edit: Earlier on I had a debug line myTable.Rows[0]["FieldName"] and myTable.Rows[1]["FieldName"]. The second one threw the exception as well, the first did not.
internal Collection<fieldDef> DefaultList
{
get
{
Collection<fieldDef> listFields = new Collection<fieldDef>();
listFields.Clear();
//Rows.Count is checked here, which is why I'm so confused...
for (int i = 0; i < myTable.Rows.Count; i++)
{
string strFieldName = "";
if (myTable.Rows[i]["FieldName"].ToString() != "") //Exception happens here
{
strFieldName = myTable.Rows[i]["FieldName"].ToString();
}
FieldType type = FieldType.Character;
if (myTable.Rows[i]["FieldType"].ToString() != "") type = (FieldType)Enum.Parse(typeof(FieldType), myTable.Rows[i]["FieldType"].ToString());
//
//Other Similar lines to that above
//
fieldDef def = new fieldDef(i, strFieldName, strFieldName, type, /*other items...*/);
listFields.Add(def);
}
return listFields;
}
set
{
//Nothing negative happens here, left out for simplicity
}
}
I found the solution. Just posting in case anyone has the same problem. It's not stated in the original post, but this is called via change/edit events on the DataTable (which are triggered by button clicks and required to save settings).
The issue is that if you try to get the property within the event, the row is actually pulled from the table (like when it is being moved up or down) and the state is "detached", therefore, no longer officially in the table.
To solve this, I simply waited to access my property until after the event had completely finished (thus the row being fully placed back into the table) which required a little reworking of other parts of my code.
Hope this helps someone down the road!
I don't have the 50 rep yet to be able to comment/ask questions, so my answer is based on what I am seeing above...
To start, it would be helpful if you included what your error/exception is. That said, while you may have a row, you are not checking for null when calling the FieldName field in that row--are you sure you have a non-null value in that field, in that row? If it is null, calling .ToString() will throw an exception...I would suggest something like this:
if (myTable.Rows[i]["FieldName"] != null && myTable.Rows[i]["FieldName"].ToString() != "") //Exception happens here
{
strFieldName = myTable.Rows[i]["FieldName"].ToString();
}
This may or may not be your issue, but either way, checking for null here would be good practice and help avoid invalid operations such as trying to a null instance.
I do apology in advance if there are many variables in the following code sample that their "types" is not clear to you, it is a big library, I just can't put all of that in here, so think of it at high-level, and the name of the variables is kind of helpful too...
Problem: A "concept" can have many "relations". Each of those relations can also have many concepts, For example like a father and child, a father has many children, a child may itsself be a father and has more children ,etc...
So I want to pass the root father and get all the hierarchy and write it to a file ...
The high-level code I am using is this, THE PROBLEM IS THAT it Crashes by a Null exception when it gets the child that has no more children. So its object is null in this line:
oUCMRConceptReltn = moTargetConceptList.ConceptReltns.get_ItemByIndex(i, false);
So I thought well let's put a not null check around it, yeah fixes the crash BUT after it sees the first leafe, it doesn't go further and algorithm stops.
So Something is wrong with the way I am calling recursion, but can't figure it out.
private void MyLoadMethod(string sConceptCKI)
{
UCMRConceptLib.UCMRConceptLoadQual oUCMRConceptLoadQual = new UCMRConceptLib.UCMRConceptLoadQual();
//Fill out UCMRConceptLoadQual object to get new list of related concepts
moTargetConceptList.Load(oUCMRConceptLoadQual;
// WHEN IT IS ZERO, THERE ARE NO MORE CHILDREN.
int numberofKids = moTargetConceptList.ConceptReltns.Count();
if (numberofKids == 0)
return ;
for (int i = 1; i <= numberofKids; i++)
{
oUCMRConceptReltn = moTargetConceptList.ConceptReltns.get_ItemByIndex(i, false);
//Get the concept linked to the relation concept
if (oUCMRConceptReltn.SourceCKI == sConceptCKI)
{
oConcept = moTargetConceptList.ItemByKeyConceptCKI(oUCMRConceptReltn.TargetCKI, false);
}
else
{
oConcept = moTargetConceptList.ItemByKeyConceptCKI(oUCMRConceptReltn.SourceCKI, false);
}
//write its name to the file...now recursion: go and find its children.
builder.AppendLine("\t" + oConcept.PrimaryCTerm.SourceString);
MyLoadMethod(oConcept.ConceptCKI);
}
return ;
}
Just as a side note, the check for number of kids being 0 is redundant, because you're never going to enter the loop.
The algorithm looks okay for what you want to do. You don't need to return anything in this case because your algorithm uses a side effect (the appendLine) to give your output.
I don't know C#, but it looks to me as if you're using some variables that are not local to the function, like oUCMRConceptReltn and oConcept. If they're not local to the function, different recursive invocations can change those values in unexpected ways. Recursive functions should almost never write to a variable outside its own scope.
Most indexes in c style languages are 0 based. So don't loop through 1 to numberofKids, loop 0 to numberofKids-1.
for (int i = 0; i < numberofKids; i++)