Entity Framework 4.1 To know the which Foreign Key constraint is violated during deletion - entity-framework

I have started using Entity Framework 4.1 with Code first. I really love this over the previous ado.net techniques.
I have a very simple situation in which there is a department table and an employee table in database. Each employee belongs to a department and a department has got many employees. The business rule is : While, deleting a department, if there are any associated employees, it should not allow deletion. I can write a small method just before deletion and check the dependancy. However, since my project is a much complex one with more than 300 db tables, I hate to do this. The relationships gets changed frequently which results in lot of changes in all the delete methods of the project.
In ado.net, in similar situations, I used to parse the exception thrown and get the name of the particular Foreign key constraint which was violated. Based on the name of the violated FK constraint, I used to give appropriate error message to client. This technique worked well even in a fairly large project with more than 150 tables.
How do I do a similar thing in EF ? How do I get which FK is violated when SaveChanges() is called ?

You need to get the Message of the inner most exception(usually its a SqlException). Then you can extract the FK name from that string and check which FK is violated.

Related

Deleting an Entity with related data and Cascading Deletes defined in SQLServer

I'm getting the following error when I SaveChanges after Removing an entity that has related entities containing data in the context as well. (The entity I'm deleting has the unique Primary Key). I have Cascading Delete configured at the SQL Server database level for the relation between the primary key table and the foreign key table.
"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 su...
The primary entity has its related data loaded explicitly prior to me removing the primary from the context. I assumed that EF and SQL Server would take care of the cascaded delete for me. If the related entity has no data the delete (of the primary entity) works fine. If there is data in the related entity, I get the error above.
Any suggestions?
The lesson is that EF has a learning curve. Keep exploring.
Anyway, I was "deleting" entities by setting the state to "Deleted" then calling SaveChanges. This seems to work fine if the entity has no related data. However, if you have an entity that has related "child" entities, you need to call Remove on the parent entity for the "delete" to cascade through the graph. Live and learn. I'm pretty sure this is the answer. I think for the time being I'm going to stop setting State for deletes and use Remove instead.

Checking record with a foreign key exists

Should i check the existence of foreign key with an sql request or should I just try to insert and catch if it fails?
I can check if the key i'm referencing exists or not.
My question is more of a theoretical: Catching an exception vs. querying db one more time for every insert.
For example say you have two tables, Cats and Humans. Cats has a foreign key referencing Human. Before I try to insert a Cat should I check if a human with given cat's owner column exists or should I try to insert blindly and catch if it fails.
This is not a simple answer and it really depends on your application requirements.
Though as a general rule of thumb you should avoid counting on exception being thrown as a part of the normal application flow and there are a couple of problems with using exceptions.
Firstly when receiving SQL Exception you'd need to identify the source of exception and this can be complex and database specific (see here for details: How to catch a specific exception in JDBC?)
Secondly even when you manage to restrict your exception code to the referential integrity ones you'll still face the task of identification of the source of the problem should the Cat reference both a Human and its favourite Food.
In addition, even when you managed to identify that the source of error is a missing referential integrity there can a few reasons for it (so rather than simply inserting the new row you'd require some additional investigation). Imagine that you want to insert a cat for the 'Dorothy Smith', while you're trying to do so Dorothy got married (likely the cat was a wedding present from the spiteful mother-in-law ;) and changed her name to 'Dorothy Griffith'. So now when you try to insert the cat, you'll duplicate Dorothy in your database, if you just blindly insert a new record.
Moreover due to the reason described above, it makes sense to use artificially created id's for foreign key (rather than a set of fields which uniquely identifies the user). In such case you'd need to obtain this internal id first (there are a couple of ways to work around it if you don't want you application to know about the identifiers, with stored procedures and using ORM framework such as Hibernate being the most common one).
Having said that, I can still imagine a situations where handling the exceptions will have its benefits, mostly when you need to address a particular performance requirement. The example of such situation can be a trading system where you've got currencies and a fast ticking exchange rates for them. Since it happens so rarely that the new currency is introduced it can be treated as a kind of an exceptional situation and it doesn't make sense to check whether it exists (though in a correctly designed system this will only save you from calling the hashing function for checking whether the currency exists as surely you cache all the currencies internally, which in fact might be faster than wrapping the db call with try ... catch ... block).
So in summary try not use the exceptions, but work around the issue with correctly defining your application logic and fall back to using exceptions if you really have to.
This paragraph is present in the question
i.e For example say you have two tables, Cats and Humans. Cats has a foreign key referencing Human. Before I try to insert a Cat should I check if a human with given cat's owner column exists or should I try to insert blindly and catch if it fails.
Here it is mentioned that CAT has a foreign key referencing HUMAN.
So there is no need of checking whether HUMAN have a key(record for) which you are inserting as foreign key in CAT table.
Because DB throws
integrity constraint (FK_T_NAME) violated - parent key not found exception
Suppose if you are using Oracle DB then it throws following exception
ORA-02291: integrity constraint violated - parent key not found
So whenever you get this exception it means the value you are inserting as foreign key in CAT table is not present in HUMAN table.
Same I tested using JDBC it gives following error
Caused by: java.sql.SQLIntegrityConstraintViolationException: ORA-02291: integrity constraint (FK_T_NAME) violated - parent key not found

optimistic concurrency exception was handled by the user code

I'm using MVC4 with Entity Framework 4.1.
Initially we have created an Ado.net entity model from database. In the .edmx file, some of the tables that are in the database are not visible as they dont posses the primary key on particular table.
As our project is moving forward, we need to update to one of the log tables which dont have a primary key field.
So, we modified our .edmx file instead of modifying in the database. our client asked us not to modify the database fields. we have modified the .edmx and created a pk on one of the exisiting field in the table(say tbl_log table).
we are trying to update the tbl_log. But it gives an error message as Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
I've seen much of questions in stack overflow and also googled a bit, but could not find any solution.
Even i've tried refreshing the ObjectStateManager entries but it still points to the same error.
Here is my code
tbl_log log = new tbl_log();
Entity.ObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Modified);
log.LoginId = strLoginId;
log.Password = strPassword;
log.IPAddress = strIpAddress;
log.Date_Time = DateTime.Parse(DateTime.Now.ToString());
log.sessionId = new Guid(strSessionId);
Entity.AddTotbl_log(log);
Entity.SaveChanges();// optimistic concurrency error
Please help
Thanks,
Karthik
Your model must represent the database schema. If you add a PK to the model it should exist in the database as well, otherwise you will get errors. It's generally bad practice to not have a PK on any table, even if the table is an audit log table.
What the exception is telling you is that the object tracker cannot determine if the state of the object has changed since the last call to the database. This is because the PK you have set is still 0 even after the framework has sent the insert/update query.
Unfortunately there is no good way to work around this. I would suggest (as I think Microsoft does) to add a primary key column to every table in your database.
EDIT - From comments
As the PK is used to track the object, if you have set the PK to have a StoreGenerationPattern of Identity in your model it will be expecting the value to change. When it doesn't change then it will throw the error your are seeing. Try changing the StoreGenerationPattern to None as then EF won't be expecting your faux-PK to change

Delete object and all its child objects in Entity Framework?

I've been trying to find the answer to this question here. Several people seem to ask similar things, but I don't get the answers. I have an EF entity with a bunch of child entities (one-to-many relationship). I want to be able to delete the "parent" entity and have all the child entities deleted at the same time.
Some people mention "Cascade Delete" should be set on both EF model and database (Sql Server in my case). The problem is:
I have absolutely no idea how to do this (seems to be implied in those answers that you should know, but sorry...)
I have a feeling I've run into a similar problems before and found an answer somewhere that was simpler than setting this Cascade Delete. I may be wrong, maybe it is the only way, but if there is a simpler solution I'd like to know.
In either case, a clear example of how to get this working would be greatly appreciated!
In SQL Managment Studio go to your database and find the table where there should be a foreign key. Add a foreign key to the table pointing to the other table. I assume you know how to setup a foreign key. In the foreign key setup at the bottom of the dialog window you'll see a Delete property. Set it to Cascade. This will cause any dependent rows to be deleted whenever the parent row is deleted. Then go and update your data model in Visual Studio. Everything should be setup for you now.
Here is some relevant documentation on MSDN. Note though that there appears to be an error in the example. I received the following error from the EDMX designer when using this configuration.
Operations cannot be specified on ends with multiplicity '*'.
You should set the OnDelete property to Cascade for the end will be triggering deletes on the other end.
As an example, in a relationship involving customers and orders where you would like to have a customer's orders deleted along with the customer, you should set the OnDelete property for the Customer role to Cascade.
Note that only objects that have been loaded into the ObjectContext will be affected by a cascading delete. You will be relying on the cascading delete that you set in the database to look after any other records.

Can I force multiplicity/assocations with Entity Framework?

I have the following table structure that Entity Framework is correctly returning as a one-to-many:
Patient
{
PatientId PK
}
Death
{
DeathId PK
PatientId FK
}
Unfortunately this DB design is wrong as you can only have one Death per Patient. The design should of been like this instead:
Death
{
PatientId PK
}
However, this is a production system and the DB is not able to be changed. I am writing a new ASP.Net MVC front-end, so I'm rewriting the DAL layer using Entity Framework.
When I call Patient.Death, I get a collection of Death. I only want it to return me a single or null Death (as the Patient may not yet be dead).
So, I went wading into the Model and tried to change the End2 Multiplicity of the assocation to: 0..1 (Zero or One of Death), but when I build the project I get the error:
Multiplicity is not valid in Role
'Death' in relationship
'RefDeath23'. Because the
Dependent Role properties are not the
key properties, the upper bound of the
multiplicity of the Dependent Role
must be *.
Can anyone tell me how, if possible, I can force this to be a zero or one association?
Can you make the EF do what you want? Sure; just lie to the EF about your DB metadata. You can do this by generating your DB against a "correctly" designed DB or by manually editing the SSDL.
However, think twice before you do this.
The EF makes this difficult, I suspect, for a very good reason: Your DB, for worse or better, allows this. By creating a model which doesn't, you would be setting yourself up for a runtime error should you ever encounter this data condition in the wild, because there would be no way to load it into your model. You would be unable to work with such a person at all until you (externally) fixed the bad data in the DB.
Your EF model should match your database. So if the database is wrong, then the EF model should also be "wrong".
What you can do is to implement this restriction in the business layer.