I am trying to delete an "AttendeeEvent" from the database with EF4, however I am getting the following error:-
The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.
My code is as follows :-
public void UnRegisterCurrentUserForEvent(int eventId)
{
Attendee attendee = GetOrCreateAttendeeForCurrentUser();
AttendeeEvent av = attendee.AttendeeEvents.SingleOrDefault(x => x.EventID == eventId);
if(av != null)
{
attendee.AttendeeEvents.Remove(av);
}
this.ObjectContext.SaveChanges();
}
I tried to change the End 2 On Delete from the properties in the .edmx however when I set to cascade, I am getting an error:-
Error 1 Error 132: cannot have operation specified since its multiplicity is ''. Operations cannot be specified on ends with multiplicity ''
Can you guys help me out
Thanks for your help and time
You are only removing the AttendeeEvent from the collection of attendee events for an Attendee. So suppose you have an attendee A and event AV and you remove AV from A. What should happen inside the database? You haven't actually removed AV. You've only said that A should no longer be related to AV. So inside your database, the foreign key from AV to A is set to NULL, which is not allowed by your database model.
The fix is simple: replace the line where you remove the event from the attendee with the following line:
this.ObjectContext.AttendeeEvents.DeleteObject(av);
Related
I have an Entity Product who has a collection of Suppliers (which is also an Entity) and i have a Contract Entity who has a collection of Products. A contract can have multiple products, even 2 same products but with a different Supplier.
When i try to add this second product to my contract (same product but different Supplier this time) EF seems to ignore it and doesn't add it to the Contract.Products collection. No errors but it doens't add it. How can i bypass this behavior or setup my model/logic in a way that i can perform this action?
Code:
// THIS CONTEXT RESIDES IN A USING BLOCK
// THE updateContracts.Products ARE COMING FROM ANOTHER CONTEXT and we are receiving this entity as a parameter
// fetching the contract we are updating from database
Contract contractFromDB = ctx.Contracts.Include(s)(...)Where(p => p.ID == updateContract.ID).FirstOrDefault();
// list to populate the products we have added
List<Product> productsToAddToDBContract = new List<Product>();
foreach (Entity.Product product in updateContract.Products)
{
if (!contractFromDB.Products.Any(prod => prod.ProductName == product.ProductName))
{
// tried detaching it but didn't work
//ctx.Entry(product).State = EntityState.Detached;
productsToAddToDBContract.Add(product);
}
}
foreach (Product product in productsToAddToDBContract)
{
// get these from DB and add those to DB contract products
Product productToAdd = ctx.Products.Include(p=> p.Suppliers).Where(prod=> prod.ProductName == product.ProductName).FirstOrDefault();
if (productToAdd != null)
{
// HERE IS WHERE EF DOESN'T ADD THE SECOND PRODUCT (WHICH IS THE SAME BUT FROM ANOTHER SUPPLIER)
contractFromDB.Products.Add(productToAdd);
}
}
Thank you very much.
EDIT:
I tried to remove the line where i fetched my product from Database
Product productToAdd = ctx.Products.Include(...).Where(...).FirstOrDefault();
and just use the product i already fetched before and passing with the updateContract.Products, i got "The relationship between the two objects cannot be defined because they are attached to different ObjectContext objects."
so i went and attach the product from this iteration:
foreach (Product product in productsToAddToDBContract)
{
// removed this line:
// Entity.Product productToAdd = ctx.Products.Include(p=> p.Suppliers).Where(prod=> prod.ProductName == product.ProductName).FirstOrDefault();
// and added this one
ctx.Products.Attach(product);
contractFromDB.Products.Add(product);
}
then i received '"Attaching an entity of type 'Supplier' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate." Note that the product already has a supplier attached/included to it but from another context (same as the product's context).
This has to regarding the relation of Product and Supplier i think, or maybe because i am using different contexts, i don't know but i will investigate further and post back.
Feel free to contribute in any way of course :)
The issue was my model structure, i can't elaborate on how it was but the related entities relation was not setup correctly, i have created a new entity that holds a ProductId-SupplierId and others, tweaking it till i got what i wanted. The reason why i got these errors (stated above) was because i didn't attach all the related entities when performing actions, when i refered the proper related entities to my product, the errors went away... :)
Hope this helps someone and forgive me for the somewhat unclear solution, i am in the middle of this project and time is an issue, for know the company wants a working solution not a clean one so i didn't not everything down ...
Kind regards!
My problem is with the generic "Delete" in the BidController I am getting the typical Error:
The DELETE statement conflicted with the REFERENCE constraint "fkw_....". The conflict occurred in database table ..., column ....
The statement has been terminated.
Thank you so much for any and all help.
Try updating the ActiveBidId with a null value and then delete the bids.That way you break the link between the Item and Bid and than you can remove the Data from Bids.
Try making the relationship as OPTIONAL. This way your items can have null Foreign Keys.
If you are using database first approach:
CREATE TABLE Item(
ItemId INT PRIMARY KEY,
ActiveBidId INT NULL FOREIGN KEY REFERENCES Bid(BidId)
// ...
);
If you already created the table, then you can alter your table as follows:
ALTER TABLE Item
DROP CONSTRAINT FK_ActiveBidConstraint -- The name of your constraint
GO
ALTER TABLE Item
ADD CONSTRAINT FK_ActiveBidConstraint FOREIGN KEY (ActiveBidId) -- The name of your constraint
REFERENCES Bid(BidId);
Apparently I am able to set the GUID to null, so I am posting a simple answer.
In my BidController I have updated my code:
item = null;
This removes the reference to the bid and so the bids are free to be removed!
I have a function that get a Book entity, and checks whether it already exists in the database.
If it already exists, the function needs to update the entity in context.
So when I use the Find function to check whether it exists, the following error is thrown:
Attaching an entity of type 'Books' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.
But when I use the Any function to check that, the code work fine.
My guess is that the Find function Attach the entity (to context) but Any not doing it.
Can someone give an explanation please?
The Find function:
public IHttpActionResult PutBook(Books book)
{
if(db.Books.Find(book.id) == null)
{
db.Entry(book).State = EntityState.Modified;
}
.
.
}
The Any function:
public IHttpActionResult PutBook(Books book)
{
if (db.Books.Any(b => b.id.Equals(book.id)))
{
db.Entry(book).State = EntityState.Modified;
}
.
.
}
Sorry if I have English errors.
Yes, Find fetches an entity from the database and attaches it to the context if it's not already in its cache. So at that point there is a Book instance in the context's cache and then you try to attach another instance to it. That's not allowed, because EF's cache is designed as an identity map.
The second snippet obviously doesn't materialize a Book instance: it runs a SQL query that only returns a bool.
I'm encountering an error with Breeze.js version 1.4.12. I have an entity, OrderLine, that has a compound primary key consisting of one GUID field (OrderId) and one integer field (LineNumber). This entity has a self-referencing foreign key, consisting of two fields: DependsOnOrderId and DependsOnLineNumber.
When creating a new instance of the OrderLine entity, and passing an object of initial values, I can assign values to the foreign key fields and everything works as expected. However, my issues lies when trying to assign values after entity creation. Assigning a value to the DependsOnOrderId property works correctly. When I assign a value to the DependsOnLineNumber property, I receive an error message: Type Error: undefined is not a function. This error occurs at line breeze.debug.js:4275 and a debugging session shows that it is trying to run a toLowerCase() method on the integer field value of the compound key.
The two lines that appear to be causing the issue are referenced below:
if (kp.dataType === DataType.Guid) {
keyValues[i] && keyValues[i].toLowerCase();
I was able to resolve this issue satisfactorily by adjusting the lines to read:
if (kp.dataType === DataType.Guid) {
keyValues[i] = keyValues[i] && ( ( keyValues[i].toLowerCase && keyValues[i].toLowerCase() ) || keyValues[i] );
This was only put together as a proof of concept to resolve the issue and has not been tested in all cases, but it ensures that when comparing a non-GUID value that is part of a GUID/non-GUID composite key, a toLowerCase() call is not attempted against a value that does not have that method.
Has anyone else encountered this error or have suggestions for fixing? I was thinking of putting together a pull request on GitHub, but wanted to check to see if there were other instances of this issue, or possible side effects with my suggested fix.
Thanks!
Your fix looks good, and I've added it to breeze-client#2.0.0-beta.1
Thanks for your help on this. And sorry it took so long.
I have successfully used EF4 to insert rows automatically with a server generated GUID:
http://leedumond.com/blog/using-a-guid-as-an-entitykey-in-entity-framework-4/
Now how does one perform this task if there exists a RowID (guid) and ParentRowID (guid) with a primary-foreign key constraint between the two? What would I set .ParentRowID to?
NewCut = New Row With
{
.ParentRowID = .RowID
}
SaveChanges throws a fit every time.
The fact that the primary key is a GUID is in fact irrelevant because I attempted the same test using a standard autogenerated integer without success.
The solution is as simple as the one you have posted.
Just create both parent and child entities in code, do not set Entity Key and not forget to set StoreGeneratedPattern for all server-generated Guid columns.
Then perform either MasterEntityInstance.Children.Add(ChildEntityInstance), or ChildEntityInstance.MasterEntity = MasTerEntityInstance and call SaveChanges.
After the SaveChanges call both guid properties will be populated with the correct Guid values, and ChildEntity.MasterEntity Entity Key will be populated with the necessary MasterEntity Entity Key value.