C# use field 1 value if field 2 empty - c#

I am running through a set of records using a for each loop, and also doing simple checks to ensure that good data is inserted into a database table.
Sometimes the dataset can be missing the LegistarID value, the change I need to do in my code, is to add a check for LegistarItem,
if the value of LegistarID is missing, but the AgendaItem value is not, then assign the value of AgendaItem to LegistarID
if LegistarId is missing, and there is also no AgendaItem value, then return a message to the user, to let them know that these values need to be present in the dataset they are trying to import.
I know it does not sound complex, but I am having a hard time making this change successfully. I need a bit of help if possible, please.
Here is my code as I currently have it:
if (ModelState.IsValid)
{
using (Etities db = new Entities())
{
foreach (var i in meeting)
{
if (i.MeetingID == 0)
{
message = string.Format("This file is missing the Meeting ID value of at least 1 record. \n Verify that the data you are trying to upload meets the criteria, and then try to upload your file again.", i.MeetingID);
return new JsonResult { Data = new { status = status, message = message } };
}
else
{
// development
var compositeKey = db.MeetingAgenda.Find(i.MeetingID, i.AgendaItem);
if (compositeKey == null)
{
// Add new
// development
db.MeetingAgenda.Add(i);
//
}
else
{
// Serves as an update, or addition of a previously imported dataset
db.Entry(compositeKey).CurrentValues.SetValues(i.MeetingID);
db.Entry(compositeKey).State = EntityState.Modified;
}
}
}
db.SaveChanges();
status = true;
}
}
else
{
message = string.Format("Please, verify that the file you are trying to upload is correctly formatted, and that the data it contains, meets the expected criteria, then click the upload button again. \n Thank you!");
return new JsonResult { Data = new { status = status, message = message } };
}
I think that part of the code I need is something like this:
else if (i.LegistarID == 0 and i.AgendaItem != 0)
{
i.LegistarID = i.AgendaItem
}
I just am unsure how in the current code place it.

I would check all rows before returning a result.
if (ModelState.IsValid) {
var errors = new List<string> ();
var rowCounter = 1;
using (Etities db = new Entities ()) {
foreach (var i in meeting) {
if (i.MeetingID == 0) {
// Let the user know this row is bad
errors.Add ($"Row {rowCounter}: This file is missing the Meeting ID. Verify that the data you are trying to upload meets the criteria, and then try to upload your file again.");
}
// Check if LegistarID is missing
if (i.LegistarID == 0) {
// Check if Agenda Item is present
if (i.AgendaItem == 0) {
errors.Add ($"Row {rowCounter}: Meeting has no LegistarID and no Agenda Item. Please check data");
} else {
i.LegistarID = i.AgendaItem
}
}
// development
var compositeKey = db.MeetingAgenda.Find (i.MeetingID, i.AgendaItem);
if (compositeKey == null) {
// Add new
// development
db.MeetingAgenda.Add (i);
//
} else {
// Serves as an update, or addition of a previously imported dataset
db.Entry (compositeKey).CurrentValues.SetValues (i.MeetingID);
db.Entry (compositeKey).State = EntityState.Modified;
}
rowCounter++;
}
// If there are errors do not save and return error message
if (errors.Count > 0) {
return new JsonResult { Data = new { status = false, message = string.Join ("\n", errors) } };
}
db.SaveChanges ();
status = true;
}
} else {
message = string.Format ("Please, verify that the file you are trying to upload is correctly formatted, and that the data it contains, meets the expected criteria, then click the upload button again. \n Thank you!");
return new JsonResult { Data = new { status = status, message = message } };
}

The "if(i.MeetingID == 0)" else is redundant, because you are returning if the condition is met. So to avoid unneeded/confusing nesting I would rewrite the actual code (of the loop only) as:
foreach (var i in meeting)
{
if (i.MeetingID == 0)
{
message = string.Format("This file is missing the Meeting ID value of at least 1 record. \n Verify that the data you are trying to upload meets the criteria, and then try to upload your file again.", i.MeetingID);
return new JsonResult { Data = new { status = status, message = message } };
}
// development
var compositeKey = db.MeetingAgenda.Find(i.MeetingID, i.AgendaItem);
if (compositeKey == null)
{
// Add new
// development
db.MeetingAgenda.Add(i);
//
}
else
{
// Serves as an update, or addition of a previously imported dataset
db.Entry(compositeKey).CurrentValues.SetValues(i.MeetingID);
db.Entry(compositeKey).State = EntityState.Modified;
}
}
Then, I would add the new condition in between the MeetingID = 0 check and the rest of the code, like this:
foreach (var i in meeting)
{
if (i.MeetingID == 0)
{
message = string.Format("This file is missing the Meeting ID value of at least 1 record. \n Verify that the data you are trying to upload meets the criteria, and then try to upload your file again.", i.MeetingID);
return new JsonResult { Data = new { status = status, message = message } };
}
// *** New check on LegistarID and AgendaItem ***
if(i.LegistarID == 0)
{
// Is there a chance to fill LegistarID with AgendaItem?
if(i.AgendaItem != 0)
{
// Yes, fill it and then let the rest of the code flow peacefully.
i.LegistarID = i.AgendaItem
}
else
{
// No way: I must stop the procedure here and warn the user about this.
// return "these values need to be present in the dataset they are trying to import."
}
}
// development
var compositeKey = db.MeetingAgenda.Find(i.MeetingID, i.AgendaItem);
if (compositeKey == null)
{
// Add new
// development
db.MeetingAgenda.Add(i);
//
}
else
{
// Serves as an update, or addition of a previously imported dataset
db.Entry(compositeKey).CurrentValues.SetValues(i.MeetingID);
db.Entry(compositeKey).State = EntityState.Modified;
}
}

Related

Send row by row without duplicates

I have the following table
As you can see there is a column called Integration of type bool, all this table is shown in a DataGridView through a stored procedure that is this
CREATE PROCEDURE [dbo].[SP_Payments]
AS
SELECT 'CE-'+CardCode AS CardCode,DocType,Series,DocDate,dbo.udf_GetNumeric(DocNum) AS DocNum,
DocEntry,TrsfrAcct,TrsfrDate,TrsfrSum, Integration,Comments,SumApplied
FROM PaymentsReceived WHERE Integration = 0
This SP says to only show me those that are at 0 which is false, what I do with those that are false is to send them through a web service, I have a method that goes through each row and sends it every time it does a send sets it to true, then it disappears from the DataGridView, this method is inside a timer that fires every 5 seconds, in this method there is a condition that says if the Integration is == false, let it send, this is the method.
private async void Envio_Timer_Tick(object sender, EventArgs e)
{
try
{
ProxyBL proxy = new ProxyBL();
foreach (DataGridViewRow Datos in dataGridView1.Rows)
{
PagosRecibidos pagos = new PagosRecibidos
{
CardCode = Convert.ToString(Datos.Cells[0].Value),
DocType = Convert.ToString(Datos.Cells[1].Value),
Series = Convert.ToInt32(Datos.Cells[2].Value),
DocDate = Convert.ToDateTime(Datos.Cells[3].Value),
DocEntry = Convert.ToInt32(Datos.Cells[5].Value),
TrsfrAcct = Convert.ToString(Datos.Cells[6].Value),
TrsfrDate = Convert.ToDateTime(Datos.Cells[7].Value),
TrsfrSum = Convert.ToDecimal(Datos.Cells[8].Value),
Integration = Convert.ToBoolean(Datos.Cells[9].Value),
Comments = Convert.ToString(Datos.Cells[10].Value),
SumApplied = Convert.ToDecimal(Datos.Cells[11].Value)
};
Inte = pagos.Integration;
if (Inte == false)
{
var EnvioDatos = await proxy.EnviarPago(pagos);
}
ListarEmple();
ListarLog();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
This is the method where SendPayment comes in
This method I get the response from Services, where if the operation was successful or failed, it inserts this in a Log
Consultas c = new Consultas();
public async Task<string> EnviarPago(PagosRecibidos detalle)
{
try
{
ProxyXML xmlProxy = new ProxyXML();
string respuesta = await xmlProxy.EnviarSAP(detalle);
c.InsertarLog(1, DateTime.Now, respuesta, xmlProxy.XmlSerializado);
return respuesta;
}
catch (Exception ex)
{
throw ex;
}
}
After this method, enter the shipment, EnviaSAP
Which is where I capture the answer, if the operation was successful then give me the Integration column as "1 true"
readonly Consultas c = new Consultas();
public string XmlSerializado = null;
public async Task<string> EnviarSAP(PagosRecibidos detalle)
{
try
{
using (WSSincronizacionClient clienteSAP = new WSSincronizacionClient())
{
XmlSerializado = this.SerializarXml(detalle);
var respuesta = await clienteSAP.EnviarDatosSAPAsync(XmlSerializado);
if (respuesta.Contains("true|OperaciĆ³n Exitosa|"))
{
c.EditarIntegration(true, Convert.ToInt32(detalle.DocEntry));
}
return respuesta;
}
}
catch (Exception ex)
{
throw ex;
}
}
Everything works correctly but when sending it, sometimes it sends it double or duplicate, that is, in SAP it arrives twice, how can I do this validation, that the one that is false only enters me once, that it does not send it for any reason twice , and in which part should I do this validation
I also don't know why if you already have that validation that I only sent the fake ones, you still send it twice.
The only thing I can think of is that the time to process an individual row exceeds the timer interval, therefore you might be iterating over the same item in two handler calls in parallel, because there isn't enough time for the other handler to complete its processing.
Maybe you could flag the row when you're fetching it, and save the changes so that flag could act as a discriminator for other timer tick handler calls to ignore the row:
foreach (DataGridViewRow Datos in dataGridView1.Rows)
{
var alreadyProcessingRow = Convert.ToBoolean(Datos.Cells[{ProcessingFlagColumnIndex}].Value);
if(alreadyProcessingRow)
continue; //skip the row, don't reprocess it
Datos.Cells[{ProcessingFlagColumnIndex}] = true; //Mark the row as processing
PagosRecibidos pagos = new PagosRecibidos
{
CardCode = Convert.ToString(Datos.Cells[0].Value),
DocType = Convert.ToString(Datos.Cells[1].Value),
Series = Convert.ToInt32(Datos.Cells[2].Value),
DocDate = Convert.ToDateTime(Datos.Cells[3].Value),
DocEntry = Convert.ToInt32(Datos.Cells[5].Value),
TrsfrAcct = Convert.ToString(Datos.Cells[6].Value),
TrsfrDate = Convert.ToDateTime(Datos.Cells[7].Value),
TrsfrSum = Convert.ToDecimal(Datos.Cells[8].Value),
Integration = Convert.ToBoolean(Datos.Cells[9].Value),
Comments = Convert.ToString(Datos.Cells[10].Value),
SumApplied = Convert.ToDecimal(Datos.Cells[11].Value)
};
Inte = pagos.Integration;
if (Inte == false)
{
var EnvioDatos = await proxy.EnviarPago(pagos);
}
Datos.Cells[{ProcessingFlagColumnIndex}] = false; //reset the flag (not that important if you just don't care after processing)
ListarEmple();
ListarLog();
}
I'm not really sure if you can do that with that datagridview object, but in case you couldn't you could use something like a ConcurrentDictionary, and store the rows (or row Ids) you are currently processing there in order to check and avoid duplicate processing.

Move an mail of a list of mail by the id

I need to move a mail from a list of 5 mails that a class reads. This mail already has been processed by a logical that I created and has met the conditional created. The problem is that it moves those 5 emails and some do not meet the conditions. If the mail that has fulfilled the condition manages to enter the data into the database then it must be moved to the processed mail folder otherwise it must be moved to the error folder.
This is the class that gets the emails
int bufferLength = 5;
int indiceMail = 0;
string from = "mail#gmail.com>";
do
{
emailList.getEmails(bufferLength);
while(indiceMail<emailList.emails.Count)
{
indiceMail++;
}
Console.WriteLine("Reading: {0}", emailList.emails.Count);
}while (emailList.MoreAvailable);
And this is the condition to move the mails
string bodyMail = emailList.emails[indiceMail].body;
match3 = Regex.Match(bodyMail, #"(?<=Status:) (\S+\b)");
statuscompare = match3.Value;
List<String> statusList = new List<string> { "i2", "i3", "i4", "i8" };
bool ex = false;
foreach (string item1 in statusList)
{
if (item1.Contains(statuscompare.Trim()))
{
ex = true;
if (item1.Contains("i4"))
{
bool moveEmail = false;
foreach (Email item in emailList.emails)
{
if (emailList.emails[indiceMail].body.Contains("i4"))
{
// if (item.body.Contains(item1))
//{
moveEmail = true;
emailList.moveMail(item.id, emailList.config.PathSuccess);
break;
// }
}
if (moveEmail)
{
continue;
}
}
}
}
}
This is part of a class to move the mails
public void moveMail(string emailId, string folderPath)
{
string folderId = getMailFolderId(folderPath);
EmailMessage message = EmailMessage.Bind(service, emailId);
message.Move(folderId);
}
Once you process an email with error, you set the flag 'emailbool' to false, which moves every other email to the PathSuccess. Not sure how emailbool actually serves any purpose other than making sure only one email from all goes to error path.
foreach (Email item in emailList.emails)
{
// This IF statement will either be true of false for ALL items.
if (!Cmmd.Parameters["p_retorno"].Value.ToString().Equals("0"))
{
emailList.moveMail(item.id, emailList.config.PathError);
}
else
{
emailList.moveMail(item.id, emailList.config.PathSuccess);
}
}
EDIT: For new code you posted, try this to move all emails that contain any string from statusList in its body.
// This will move all emails that have one or more statusList in their body
foreach (Email item in emailList.emails)
{
if (statusList.Where(x => item.body.Contains(x)).Count > 0)
{
emailList.moveMail(item.id, emailList.config.PathSuccess);
break; // This statement will stop processing of any other emails.
}
}

Error adding user in Unity using Firebase

Here is my code for adding a new registered user to the Firebase database :
TransactionResult AddUserToDatabaseTransaction(MutableData mutableData) {
if (mutableData != null)
{
List<object> users = mutableData.Value as List<object>;
if (users == null)
{ users = new List<object>();
}
users = new List<object>();
// Now we add the new score as a new entry that contains the email address and score.
Dictionary<string, object> newUserRegistration = new Dictionary<string, object>();
newUserRegistration["Dateofbirth"] = "22/03/1980";
newUserRegistration["Email"] = auth.CurrentUser.Email;
newUserRegistration["Full Name"] = "cool";
newUserRegistration["LastLoggedIn"] = "27/06/2017";
newUserRegistration["RegistrationDate"] = "26/04/2017";
users.Add(newUserRegistration);
// You must set the Value to indicate data at that location has changed.
mutableData.Value = users;
return TransactionResult.Success(mutableData);
}
else return TransactionResult.Abort();
}
public void AddUserToDatabase() {
DatabaseReference reference = FirebaseDatabase.DefaultInstance.GetReference("users");
DatabaseReference usersaddnow = reference.Child(auth.CurrentUser.UserId);
usersaddnow.RunTransaction(AddUserToDatabaseTransaction)
.ContinueWith(task => {
if (task.Exception != null) {
information.text +=task.Exception.ToString();
} else if (task.IsCompleted) {
information.text += " Transaction complete.";
}
}
);
}
Here is a snapshot of the database:
So, I am trying to add a user to database.
I succeeded in adding them as you can see from the picture, but it is adding a zero child before the user details. Can you please tell me why is this happening ?
I have been trying to get rid of this for hours an I can not find the solution.
The problem is because of arraylist
it's setting the data by it's own index i.e 0,1 etc
so it seems like in unity it uses these indexes by default
I can access testing and inner elements
It's easier to manage data this way and access it

C# string format alignment not working

I am working on an ASP.Net core application and would like to align some text in a string.
Somehow I am not able to get this working and am probably missing something very obvious here.
So this is my code (simplified):
public class AdminController : Controller
{
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ImportOrganizations(ICollection<IFormFile> files)
{
var count = 0;
var uploads = Path.Combine(_environment.WebRootPath, "uploads");
foreach (var file in files)
{
if (file.Length <= 0) continue;
using (var reader = new StreamReader(file.OpenReadStream()))
{
var csv = new CsvReader(reader);
while (csv.Read())
{
// Fields that need to be filled
string name;
try
{
name = csv.GetField<string>("Name");
}
catch (Exception ex)
{
ModelState.AddModelError("", $"Row {csv.Row, 10}, {ex.Message}");
continue;
}
// Check if name has a value
if (string.IsNullOrWhiteSpace(name))
{
ModelState.AddModelError("", $"Row {csv.Row, 10}, Name is a required field");
continue;
}
if (await _context.Organizations.AnyAsync(o => o.Name == name))
{
ModelState.AddModelError("", $"Row {csv.Row, 3}, Organization {name} already exists");
continue;
}
// Add the new Event
var or = new Organization()
{
Name = name
};
_context.Organizations.Add(or);
}
await SaveContext();
}
}
var model = new ImportViewModel("Import Organizations", nameof(ImportOrganizations), count);
return View("Import", model);
}
}
Now when the import file does not have a value in the name field, I expect something like this in my browser:
Row 20 , Name is a required field
But I keep getting this:
Row 20, Name is a required field
Could someone help me out here?
You need to use negative value for the field width, if you want to pad value on the right side:
$"Row {csv.Row, -10}, {ex.Message}"
See Composite Formatting article for more details.
Thanks to the comment of sgmoore, I was able to resolve it.
It seems this is an issue of html, where it is not possible to use multiple whitespaces in a row.

IF-IF-Else doesn't work as I need and want

I need to know how I could handle my problem in a efficient and smart way:
I want an error-handling for user's input; I have 2 fields CustomerID and Company:
if (customerIDExists)
{
errorMessage = "...";
}
if (companyInvalid)
{
errorMessage = "...";
}
else
{
// Add user to DB
}
There could be 3 errors:
CustomerID already exists
Company has an invalid name
CustomerID AND Company is invalid at the same time
With the example above the else is for the last if (companyInvalid). How can I deal with the else that this only executes when the 1 and 2 if doesn't match?
Else if is not right because I have to check all opportunities.
Well, you could make it very explicit:
if (customerIDExists)
{
...
}
if (companyInvalid)
{
...
}
if (!customerIDExists && !companyInvalid)
{
// Add user to DB
}
Or just use the fact that you haven't got an error message:
string errorMessage = null;
if (customerIDExists)
{
errorMessage = ...;
}
if (companyInvalid)
{
errorMessage = ...; // Don't forget it could already be non-null!
}
if (errorMessage == null)
{
// No error message, so we must be fine
// Add user to DB
}
If I understand your problem the else will fire if customerIDExists is true.
Try this
if(customerIDExists)
{
errorMessage = "...";
}
else if(companyInvalid)
{
errorMessage = "...";
}
else
{
// Add user to DB
}
I've added an else if to the second condition. Now your application will check if the customerIDExists, if it doesn't it will check if the companyInvalid if it doesn't it will add the user to the database.
Now, what happens if both of these are incorrect? You'll only present on error message to your user, this will be annoying when they fix that issue and discover they have another you didn't tell them about! My suggestion would be to use a list of errors, if there aren't any then save to the database:
var errors = new List<string>();
if(customerIDExists)
{
errors.Add("Customer exists");
}
if(companyInvalid)
{
errors.Add("Company invalid");
}
if(!errors.Any())
{
// Add user to DB
}
return errors;
You can use a variable:
bool isValid = true;
if(customerIDExists)
{
errorMessage = "...";
isValid = false;
}
if(companyInvalid)
{
errorMessage = "...";
isValid = false;
}
if(isValid)
{
// Add user to DB
}
You can try old technique:
do {
if(customerIDExists)
{
errorMessage = "...";
break;
}
if(companyInvalid)
{
errorMessage = "...";
break;
}
// All is ok.
} while (false);
If you want to show all messages and don't break the proof after first error, you could use something like this:
List<string> errorMessages = new List<string>();
if (customerIDExists)
{
errorMessages.Add("...");
}
if (companyInvalid)
{
errorMessages.Add("...");
}
if (errorMessages.Count == 0) //Valid
{
}
else //Invalid
{
}
I assume you'd want to report all errors, not just the first that's encountered.
var errors = new List<string>();
if (customerIDExists)
{
errors.Add("customer id exists");
}
if (companyInvalid)
{
errors.Add("company is invalid");
}
if(errors.Any())
{
// display all error messages
}
else
{
// Add user to DB
}

Categories