I wasted the better part of the day on this and am no closer to a understanding the issue than what I was this morning.
I am looping through a set of objects and marking them for deletion. The 2nd one always causes the above exception. tb_invoice has a FK to tb_shipment.
As always, I am probably missing something very obvious, but I have stripped out so much from this code already that there is nothing left, and I am still getting this exception. This is a local SQL 2008 instance and there is of course nothing and nobody changing the invoice in between reading them and calling SubmitChanges(). Help!
myDataContext db = new myDataContext();
IQueryable<invoiceDetail> pendingInvoices
= db.GetInvoiceDetailPending();
foreach (invoiceDetail id in pendingInvoices) {
tb_shipment s = db.GetShipmentById((Guid)id.shipment_id);
db.tb_invoices.DeleteOnSubmit(
db.GetInvoiceById(s.tb_invoices.FirstOrDefault().id)); }
SubmitChanges(); // fails for the 2nd invoice
}
System.Data.Linq.ChangeConflictException: Row not found or changed
Setting the Delete action for the foreign keys in SQL Server to "Cascade" did the same. I wish I had remembered earlier that I ran into this before.
Related
Doing a learning exercise.
Trying to update the database date column for all entries to a new specific value or go through each entry and change date to a new specific value.
I tried using DataContext & Linq but it keeps telling me missing reference which its not so I have reverted to this.
var results = webDataSet.GreyList;
foreach (var elements in results)
{
elements.Date = 55;
}
webDataSet.AcceptChanges();
greyWebTableAdapter.Update(webDataSet.GreyList);
Even If i put Update in a try catch it says it is successful but it will never update the database.
Plus I'd like to thank the people who have nothing to say yet down vote my questions, its people like you who really bring the community together.
To anyone else who took advice to add .AcceptChanges(); by using this it sets the dataSets modified row value from true to false; so when you update the method looks for modified true row's however they are all false so nothing gets updated. Also the other factor to not seeing the database change is because Visual studio 2015 creates a copy of the database from your local folder and duplicates it in your bin folder, so looking for changes in your local folders database is a waste of time.
The goal is simple. I need to update the LastUpdated column in the Schedule table. I've tried several different methods to achieve that goal but with no success. I'm certain the code is pointing to the correct database and I'm also checking the correct [local] database for the changes. When a break point is set on SaveChanges(), the code halts at that point. I can see that "db" contains the updated Date/Time information for the correct record. Yet, it does not save it to the database.
Having gone through Stack Overflow, I've tried some suggestions like using Attach and setting the Entity State [to Modified]. Neither of those suggestions worked. HasChanges returns false, even though I can see the change is applied to the context variable.
Also, the class this method is in contains other methods that have no problem accessing the database and doing some inserts. The below code is just three different attempts to give you an idea on how I'm trying to do it. Any suggestions would be greatly appreciated.
public static void UpdateLastUpdated(int scheduleId)
{
using (var db = new MyContext())
{
var schedule = from s in db.Schedule where s.Id == scheduleId select s;
schedule.FirstOrDefault().LastUpdated = DateTime.Now;
db.SaveChanges();
var schedule2 = db.Schedule.Find(scheduleId);
schedule2.LastUpdated = DateTime.Now;;
db.SaveChanges();
var schedule3 = db.Schedule.Single(s => s.Id == scheduleId);
schedule3.LastUpdated = DateTime.Now;
db.SaveChanges();
}
}
You must indicate the change
db.Entry(schedule3).State = EntityState.Modified;
or
db.Entry(schedule3).Property(x => x.LastUpdated).IsModified = true;
So as it turns out, after a lot of trial and error... The issue was because the column was computed. I tried updating another column in the same table from that method and it worked fine. Then I did some research on computed columns and found that to be the problem. After removing the annotation, the code works fine. Now I just need to figure out how to get the default value set without the annotation.
Thank you to everyone who offered solutions and comments. Much appreciated!
Background:
Using C# in the ASP.Net code-behind to call a SQL stored procedure via LINQ-to-Entities.
Also, please note that I am a complete newbie to all of this.
Problem:
I'm calling a stored procedure to get the max_length of a column in my database.
It keeps returning "Sequence Contains No Elements" when utilizing .First() and (alternately) the default when using .FirstOrDefault().
The problem is, I know it should be returning the number "4500" as I've run the query in SQL to see what should be there.
Any ideas on why it would be doing this?
I've searched high and low, but I can't find anyone else who has had this problem where they know it should be returning a value.
Code:
short? `shorty = db.sp_GetMaxLength("ApplicantEssay").First();`
The result of the SQL query used in the stored procedure:
Thanks so much for any assistance you can provide!!
Edit:
The only other code involved is the ADO.Net Entity auto-generated code.
At least, it's the only other code that the program steps through when I tried to examine what was going on.
I had a hard time looking at the return and trying to figure it out, but obviously it's returning nothing):
public virtual ObjectResult<Nullable<short>> sp_GetMaxLength(string cOLUMN_NAME)
{
var cOLUMN_NAMEParameter = cOLUMN_NAME != null ?
new ObjectParameter("COLUMN_NAME", cOLUMN_NAME) :
new ObjectParameter("COLUMN_NAME", typeof(string));
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<Nullable<short>>("sp_GetMaxLength", cOLUMN_NAMEParameter);
}
Edit #2: I guess I should close this question out.
I messed around with some stuff in sql, then put it back to what I had in the first place and re-executed the stored procedure. Following that, I deleted the Entity Model, reset web.config to its original state pre-model, closed Visual studio, re-opened Visual Studio, and then re-added an ADO.Net Entity Model to the project. I then re-ran the code, stepped through it, and then all of a sudden, "4500" popped up as the returned value.
I am completely flummoxed, since all the code is exactly the same without changes, but I guess that's the power of scrapping and re-starting??? No other explanation, though I hate when it's as simple as that. :-(
Thanks to all who commented. :-)
I am updating an object of type X and its children Y using LINQ to SQL and then submitting changes and getting this error
Example Code
X objX = _context.X.ToList().Where(x => x.DeletedOn == null).First();
objX.DeletedOn = DateTime.Now;
EntitySet<Y> objYs = objX.Ys;
Y objY = objYs[0];
objY.DeletedOn = DateTime.Now;
_context.SubmitChanges();
On SubmitChanges() I get an exception "1 of 2 Updates failed", no other information as to why that happened. Any ideas?
Also the exception type is
ChangeConflictException
Sooo what was the cause of the problem
- A trigger
I did a sql profiler and saw that
When ObjY's DeletedOn property got updated a trigger updated
ObjX's property (value in table) called CountOfX
which led to an error as the SQL created by LINQ to SQL had the old CountOfX value in it.
Hence the conflict.
If you ever get this error - SQL profiler is the best place to start your investigation
ALSO NOT RELATED TO THE QUESTION
I am testing LINQ to SQL and ADO.net Framework, weirdly this error happened in LINQ to SQL but not in ADO.net framework. But I like LINQ to SQL for its Lazy Loading. Waiting for EF to get outta beta
I'm not sure what the cause of the error may be exactly, but there seem to be a number of problems with the example you've provided.
Using ToList() before the Where() method would cause your context to read the entire table from the DB into memory, convert it to an array; and then in the same line you immediately call Where which will discard the rows you've loaded, but don't need. Why not just:
_context.X.Where(...
The Where method will return multiple items, but the second line in the example doesn't appear to be iterating through each item individually. It appears to be setting the DeletedOn property for the collection itself, but the collection wouldn't have such a property. It should fail right there.
You are using DateTime.Now twice in the code. Not a problem, except that this will produce ever so slightly different date values each time it is called. You should call DateTime.Now once and assign the result to a variable so that everything you use it on gets identical values.
At the point where you have "Y objY = objYs[0]" it will fail if there are no items in the Y collection for any given X. You'd get an index out of bounds exception on the array.
So given this example, I'm not sure if anyone could speculate as to why code modeled after this example might be breaking.
In LINQ2SQL Data Context diagram select the Entity and the field where the count is stored. (A denormalized figure)
Now set the UpdateCheck = Never.
I had this kind of issue. I was debugging running single lines at a time. It turned out another process was modifying this record.
My manual debugging process was slowing down the normal speed of the function. When I ran it all the way to a line after the SubmitChanges method, it succeeded.
My scenario would be less common, but the nature of this error relates to the record becoming superceded by another function/process. In my case it was another process.
I have not been working in SQL too long, but I thought I understood that by wrapping SQL statements inside a transaction, all the statements completed, or none of them did. Here is my problem. I have an order object that has a lineitem collection. The line items are related on order.OrderId. I have verified that all the Ids are set and are correct but when I try to save (insert) the order I am getting The INSERT statement conflicted with the FOREIGN KEY constraint "FK_OrderItemDetail_Order". The conflict occurred in database "MyData", table "dbo.Order", column 'OrderId'.
psuedo code:
create a transaction
transaction.Begin()
Insert order
Insert order.LineItems <-- error occurs here
transaction.Commit
actual code:
...
entity.Validate();
if (entity.IsValid)
{
SetChangedProperties(entity);
entity.Install.NagsInstallHours = entity.TotalNagsHours;
foreach (OrderItemDetail orderItemDetail in entity.OrderItemDetailCollection)
{
SetChangedOrderItemDetailProperties(orderItemDetail);
}
ValidateRequiredProperties(entity);
TransactionManager transactionManager = DataRepository.Provider.CreateTransaction();
EntityState originalEntityState = entity.EntityState;
try
{
entity.OrderVehicle.OrderId = entity.OrderId;
entity.Install.OrderId = entity.OrderId;
transactionManager.BeginTransaction();
SaveInsuranceInformation(transactionManager, entity);
DataRepository.OrderProvider.Save(transactionManager, entity);
DataRepository.OrderItemDetailProvider.Save(transactionManager, entity.OrderItemDetailCollection); if (!entity.OrderVehicle.IsEmpty)
{
DataRepository.OrderVehicleProvider.Save(transactionManager, entity.OrderVehicle);
}
transactionManager.Commit();
}
catch
{
if (transactionManager.IsOpen)
{
transactionManager.Rollback();
}
entity.EntityState = originalEntityState;
}
}
...
Someone suggested I need to use two transactions, one for the order, and one for the line items, but I am reasonably sure that is wrong. But I've been fighting this for over a day now and I need to resolve it so I can move on even if that means using a bad work around. Am I maybe just doing something stupid?
I noticed that you said you were using NetTiers for your code generation.
I've used NetTiers myself and have found that if you delete your foreign key constraint from your table, add it back to the same table and then run the build scripts for NetTiers again after making your changes in the database might help reset the data access layer. I've tried this on occasion with positive results.
Good luck with your issue.
Without seeing your code, it is hard to say what the problem is. It could be any number of things, but look at these:
This is obvious, but your two insert commands are on the same connection (and the connection stays open the whole time) that owns the transaction right?
Are you retrieving your ID related to the constraint after the first insert and writing it back into the data for second insert before executing the command?
The constraint could be set up wrong in the DB.
You definitely do not want to use two transactions.
Looks like your insert statement for the lineItems is not correctly setting the value for the order .. this should be a result of the Insert order step. Have you looked (and tested) the individual SQL statements?
I do not think your problem has anything to do with transaction control.
I have no experience with this, but it looks like you might have specified a key value that is not available in the parent table. Sorry, but I cannot help you more than this.
The problem is how you handle the error. When an error occurs, a transaction is not automatically rolled back. You can certainly (and probably should) choose to do that, but depending on your app or where you are you may still want to commit it. And in this case, that's exactly what you're doing. You need to wrap some error handling code around there to rollback your code when the error occurs.
The error looks like that the LineItems are not being given the proper FK OrderId that was autogenerated by the the insert of the Order to the Order Table. You say you have checked the Ids, Have you checked the FKs in the order details as well ?