Error: The DELETE statement conflicted with the REFERENCE constraint - c#

I' m trying to delete a items of a table. This table have a related with another table.
try
{
db.OrganizationalUnitType.Remove(SelectedUnitType);
db.SaveChanges();
}
catch (Exception ex)
{
//TODO CODE FOR EXCEPTION
}
I have a item(item1) that not have any related with another items, when i run application i can delete this item(item1), but when I'm trying to delete another item(item2) that have related i get error,after this action when i select item1 and want to delete this get this error, but if i close the application and run again i can delete this item !!!!!!

i had same problem before and select new object solve my problem like below , 'unitID' is the primary key of item you want to delete , hope it helps you too
try
{
var NewSelectedUnitType = db.OrganizationalUnitType.SingleOrDefault(p=>p.ID == unitID);
db.OrganizationalUnitType.Remove(NewSelectedUnitType);
db.SaveChanges();
}
catch (Exception ex)
{
..
}

Related

Getting all errors on an SaveChanges() within EF Core

All,
I need to show all validation errors within EF Core. So for example
I get data by doing this :
foreach (var item in FRFT)
{
var FinancialReportingFrameworkType = new FinancialReportingFrameworkType { FinancialReportingFrameworkTypeId = item.Frfid, Acronym = item.Frf1, Name = item.Frfdescription };
_clDBContext.FinancialReportingFrameworkType.Add(FinancialReportingFrameworkType);
}
Then I want to push this data into another table but there may be some vlaidation errors. I need to track the errors.
If I do a try .. catch block, I only recieve the first error but there maybe an error on every single row I push into the databse.
_clDBContext.SaveChanges();
}
catch (DbUpdateException e)
{
if (e.InnerException != null)
{
// to be chnged to an POST HTML error code
Console.WriteLine(e.InnerException.Message);
return new OkObjectResult(e.InnerException.Message);
}
I need to do some pre-Save Changes valdiation.
Any ideas ?

How do I catch statement conflicted with the REFERENCE constraint FK

I will like to know how to catch the exception for this error message.
I tried to delete a record from a table, but the table has a FK from another table.
Thank you in advance!
Try below code:
try
{
//Your code block to delete the record.
}
catch(Exception ex)
{
if (ex.Message.ToLower().Contains("statement conflicted with the reference constraint"))
{
//Show custom error message as "need to delete parent value before delete this record."
}
}

SqlException The INSERT statement conflicted with the FOREIGN KEY constraint

The INSERT statement conflicted with the FOREIGN KEY constraint FK_Kupovina_Kupac. The conflict occurred in database OnlineApoteka, table dbo.Kupac, column 'ID'.
The statement has been terminated.
I'm really confused I do not know why we do not allow? I reported a bug, in throw ex; ?
public static void Kupi(long lekID, int kolicina, double cena, long nacinIsporukeID, string korisnickoIme)
{
SqlConnection con = new SqlConnection();
try
{
con.ConnectionString = ConfigurationManager.ConnectionStrings["OnlineApotekaConnectionString"].ConnectionString;
con.Open();
string updateLager = #"
UPDATE Lager
SET Kolicina=Kolicina-#Kolicina
WHERE LekID=#LekID";
SqlCommand cmd = new SqlCommand(updateLager, con);
cmd.Parameters.AddWithValue("#LekID", lekID);
cmd.Parameters.AddWithValue("#Kolicina", kolicina);
cmd.ExecuteNonQuery();
string insertIntoKupovina=#"
INSERT INTO Kupovina (KupacID, LekID, Datum, Kolicina, Cena, NacinIsporukeID)
VALUES (#KupacID, #LekID, #Datum, #Kolicina, #Cena, #NacinIsporukeID)";
cmd = new SqlCommand(insertIntoKupovina, con);
cmd.Parameters.AddWithValue("#KupacID", KupacAdapter.GetID(korisnickoIme));
cmd.Parameters.AddWithValue("#LekID", lekID);
cmd.Parameters.AddWithValue("#Datum", DateTime.Now.Date);
cmd.Parameters.AddWithValue("#Kolicina", kolicina);
cmd.Parameters.AddWithValue("#Cena", cena);
cmd.Parameters.AddWithValue("#NacinIsporukeID", nacinIsporukeID);
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
throw ex;
}
finally
{
con.Close();
}
}
I have a routine event for the button Buy.
When you click Kupi, should be removed from the table Lager volumes and placed in the Kupac Kupovina
protected void kupiButton_Click(object sender, EventArgs e)
{
KupovinaAdapter.Kupi(Convert.ToInt64(kupovinaGreedView.SelectedDataKey["LekID"].ToString()),
Convert.ToInt32(kolicinaTextBox.Text),
Convert.ToInt64(kupovinaGreedView.SelectedDataKey["Cena"].ToString()),
Convert.ToInt64(nacinIsporukeDropDownList.SelectedValue),
User.Identity.Name);
}
protected void kupovinaGreedView_SelectedIndexChanged(object sender, EventArgs e)
{
if (!String.IsNullOrEmpty(kupovinaGreedView.SelectedDataKey["Lek"].ToString()))
{
LekLabel.Text = kupovinaGreedView.SelectedDataKey["Lek"].ToString();
}
if (!String.IsNullOrEmpty(kupovinaGreedView.SelectedDataKey["Kolicina"].ToString()))
{
kolicinaValidator.MaximumValue = kupovinaGreedView.SelectedDataKey["Kolicina"].ToString();
}
The reason you are getting the error is because of how the database schema is defined. In particular the table Kupac is used in a relation with the table Kupovina such that the KupacID in Kupovina must match a value from the ID field in the Kupac table.
Because of this you cannot insert records into the Kupovina table using a KupacID that doesn't already exist in the Kupac table - it's a Foreign-Key Constraint violation.
You have two options:
make sure you first insert a record into the Kupac table
drop the foreign-key constraint from the database schema if that makes business-sense
But you should examine the output of the KupacAdapter.GetID(korisnickoIme) which is what is supposed to provide the KupacID value. If this method for some reason does not return a valid ID (one from the Kupovina table) than the insert will fail as explained above.
In case you are wondering why the Exception is not begin "handled" than that is because of the code in your catch block. You are basically taking the exception and re-throwing it which is sort of pointless. You might as well just not have a catch block at all..
try {
// ...
}
catch (Exception ex) {
throw ex; // <--- this just re-throws the same exception that was caught!
}
finally {
}
Is, for the most part, nearly equivalent to:
try {
// ...
}
finally {
}
The difference is only in how much of the stack trace is preserved along with the exception, but the exception is bubbled up nonetheless.
The Kupac table does not have the KupacID value in that table that you are trying to insert into the Kupovina table
The KupacID column in the Kupac table is the primary key, while the KupacID column in the Kupovina table is the foreign key pointing back to the primary key
Read up on Foreign Keys
Yes, you are catching the key violation with catch (Exception ex) - however you then rethrow the Exception there.
Do you have an error handler in the calling routine?
throw ex - does not "handle" an error - it is simply raising another (although, the same one in this case - the one that has been caught)
If you are expecting this specific error then you should catch this specific error by catch (SqlException ex) - and then check for this particular error. If it is not this error then throw ex; back up the call-stack... If it is this error then you can ignore (but it would be better to just avoid this kind of INSERT in the first place...)

Handling duplicate insertion

So I've got this piece of code which, logically should work but Entity Framework is behaving unexpectedly.
Here:
foreach (SomeClass someobject in allObjects)
{
Supplier supplier = new Supplier();
supplier.primary_key = someobject.id;
supplier.name = someobject.displayname;
try
{
sm.Add(supplier);
ro.Created++;
}
catch (Exception ex)
{
ro.Error++;
}
}
Here's what I have in sm.Add()
public Supplier Add(Supplier supplier)
{
try
{
_ctx.AddToSupplier(supplier);
_ctx.SaveChanges();
return supplier;
}
catch (Exception ex)
{
throw;
}
}
I can have records in allObjects that have the same id. My piece of code needs to support this and just move on to the next and try to insert it, which I think should work.
If this happens, an exception is throw, saying that records with dupe PKs cannot be inserted (of course). The exception mentions the value of the PK, for example 1000.
All is well, a new supplier is passed to sm.Add() containing a PK that's never been used before. (1001)
Weirdly though, when doing SaveChanges(), EF will whine about not being able to insert records with dupe PKs. The exception still mentions 1000 even though supplier contains 1001 in primary_key.
I feel this is me not using _ctx properly. Do I need to call something else to sync it ?
Found it, had to change something in the Add() method:
public Supplier Add(Supplier supplier)
{
try
{
_ctx.AddToSupplier(supplier);
_ctx.SaveChanges();
return supplier;
}
catch (Exception ex)
{
_ctx.Supplier.Detach(supplier);
throw;
}
}

Removing a batch of records from Entity Framework when there is an error

I am batch adding a bunch of records from an internal system to our web database server (eBilling type data). I have a problem where if there is a data error (seperate issue), every add after that errors out.
foreach (InvoiceHeader invoiceHeader in invoiceHeaders)
{
rrn++;
db.AddToInvoiceHeaders(invoiceHeader);
if (rrn >= RECORDS_AT_A_TIME)
{
try
{
db.SaveChanges();
rrn = 0;
}
catch (Exception e)
{
string errorText = "Error in blah blah blah \n\n";
errorText += "Error: " + e.ToString();
Log.Error(errorText);
// Delete out bad record or entire set of records here.
}
}
}
So the first 500 may go good, then I might get an invalid date. Nothing else gets added to the server and the logs get slammed with errors and crashes.
How can I either clear out the one record in error OR just clear out that batch of records? So it can finish properly and we can go back and fix the errors thus adding back the missing data.
Update: I want to be able to just log the error, remove the problem record(s) and move on. In this case it happens to be a date issue, I am not looking for solving this one instance, but all future unknown issues. How do I do the // Delete out bad record or entire set of records here.?
With your current implementation you are already processing each item 1-by-1, therefore, if an error occurs on one of them that you can handle then simply do so and continue processing. Also, don't catch a general Exception, be more specific in what exceptions your code should expect e.g.
try
{
...
}
catch (SqlTypeException)
{
...
}
This is probably a less than ideal solution, but what seems to work for what I need to move on.
foreach (InvoiceHeader invoiceHeader in invoiceHeaders)
{
rrn++;
if (rrn >= RECORDS_AT_A_TIME)
{
try
{
db.SaveChanges();
rrn = 0;
}
catch (Exception e)
{
string errorText = "Error in blah blah\n\n";
errorText += "Error: " + e.ToString();
Log.Error(errorText);
// Throw out all of these records so we can move on.
// Probably not the best solution, but it works.
db.Dispose();
db = new db_Entities();
}
}
}

Categories

Resources