Why is ON DELETE SET NULL still not implemented in the Entity Framework 6? Is there a snag? - entity-framework

It still is not possible to configure a relation with the ON DELETE SET NULL rule using Entity Framework code first. As a workaround you have to load all the related entities in memory and then on deletion of the parent entity EF will issue SQL commands to set their foreign keys to Null.
This, while it is trivial to implement this yourself using something like:
protected override void Seed(Context context)
{
context.Database.ExecuteSqlCommand("ALTER TABLE dbo.Guests DROP CONSTRAINT Guest_PreferredLanguage");
context.Database.ExecuteSqlCommand("ALTER TABLE dbo.Guests ADD CONSTRAINT Guest_PreferredLanguage FOREIGN KEY (LanguageID) REFERENCES dbo.Languages(LanguageID) ON UPDATE NO ACTION ON DELETE SET NULL");
}
(Example take from this post.)
I can see no problems with this approach: Loaded child entities will remain in sync with the database because EF will update (set to null) their foreign keys and Reference properties, and that other records in the database are affected does no harm as they have not been loaded anyway.
So, why is this feature still missing then? Is there some hidden snag?

The feature is probably not implemented because normally changes only affect the objects which are actually in the unit of work. Cascades are not scalable.
And I also think soft deletes are better in most cases. Maybe thats something for you?
You might also want to look into Domain Driven design. That also covers the correct use of units of work (with aggregates).
Btw your solution edits the database in the seed method. It might be better to do that a Up() method of a migration.

This feature is available in Microsoft.EntityFrameworkCore Version=3.1.10.0 onwards.
modelBuilder.Entity<Guests>()
.HasOne<Languages>(g => g.Language)
.WithMany(l => l.Guests)
.HasForeignKey(g => g.LanguageID)
.IsRequired(false)
.OnDelete(DeleteBehavior.SetNull);
Note, DeleteBehavior.SetNull

Related

Updating the ID of an instance in JPA

I am using JPA annotations(hibernate implementation), and i want to change the ID of an entity by merging it.There is any annotation or solution to avoid duplicating then removing the entity?
This is not possible using JPA, for good reasons:
you have an entity removed from the persistence context and you want to reattach it, how possibly could it be connected to the original row it was modified from if you remove the only way to make the connection? Ok, let's assume we store the original id and try to go from there, but now since id is modifiable there is 0 guarantee that it wasn't changed by some other process as well while it was detached, making our stored original id useless and causing complete chaos.
You can do workarounds though:
use a native query to modify the row
don't use this column as your primary key but instead create a new one with generated sequences
duplicate then remove entity as you said is also completely valid and safe as it's in the same transaction
you can change Entity's id in jpa using JPQL like this example :
public void updateUsername(User userToUpdate,String newUserName) {
EntityManager manager=ConnectionDao.getConnecting();
User user=find(userToUpdate.getUsername());
manager.getTransaction().begin();
manager.createQuery("update User u set u.username=\'"+newUserName+"\'").executeUpdate();
manager.getTransaction().commit();
return;
}

Best way to save a sometimes store-generated column

I have an entity that has one column with strange behavior. On insert sometimes it is set to a value passed by the application and sometimes it uses the newly-created identity value from another column. This is currently implemented using a stored procedure. Is there a clean way to do this with Entity Framework?
I'm using Entity Framework 6 with Code First, but I'm not doing database generation or using migrations.
I know that I can essentially use a DbContext.Database to manually call a procedure as if I'm not using EF, but then I lose all of EF's automatic updates of the entity on save, participation in a SaveChanges transaction, etc. What's the best way to mitigate this?
Edit:
I will try to describe my ideal solution in pseudo code. The question is really how close can I get to this with real code given Entity Framework 6's current functionality.
Ideally I could just configure a column to sometimes be an "identity" column. In other words, sometimes generated by the database on insert, sometimes not. Something like this:
public sealed class WidgetConfiguration : EntityTypeConfiguration<Widget>
{
public WidgetConfiguration()
{
HasKey(d => d.Id);
Property(e => e.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(e => e.Number)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.SometimesIdentity);
MapToStoredProcedures(s => s.Insert(i => i.HasName("InsertWidget")));
}
}
Since this is not possible, I'm wondering if there is some other way of participating in SaveChanges so that I can take advantage of the EF goodness like dependency analysis and automatic transaction management rather than:
Creating a transaction
Populating a context with new/changed entities that a Widget depends on and saving it.
Inserting the Widget.
Populating a context with new/changed entities that depend on the Widget and saving it.
Committing the transaction.
In other words, is it possible to tell EF, "Hey, I know how to save Widgets. Here's a callback when you need to save one." or something like that?
EF does not refresh the entities that may be affected by a StoredProcedure you have to do it manually by calling:
dbContext.Entry(myEntityToRefresh).Reload();
//or
dbContext.Entry(myEntityToRefresh).ReloadAsync();
Please change the title of this question. It says nothing.

Manually editing database in code first entity framework

I have been trying out EF 4.1 (code first) with MVC 3. I am thinking ahead to when the application will need changes. I tested a couple of scenarios. I like the idea of manually editing the database when the model (my POCOs) would changed.
ASP.NET error when I change the model :
"The model backing the 'CTCMContext' context has changed since the database was created. Either manually delete/update the database..."
Now, it says that I can "manually update the database", but I did and still get the same error. Am I missing something !!?!
EDIT
Does this have to do with the model hash generate by EF ?
I have had some struggles with this as well. I found that when you let EF create your database for you that a table named dbo.EdmMetadata is created and this is where/how EF tracks the state of the model. I found that if you delete this table after the database has been initially created you will put things into "manual mode" where you can now manually add/remove columns, tables, etc. from your database and EF will not throw the error that you are seeing.
If however you want to keep having EF update your database as you make changes to your model, you will need to create and call a ContextInitializer class that inherits from either DropCreateDatabaseIfModelChanges or DropCreateDatabaseAlways depending upon the behavior that you want to have happen.
change the class with the new fieldnames, delete the table "EdmMetaData" then recompile your app.
You will be responsible on modifying the fieldname on your views.
it works for me.
As I can see, there aren't really any methods built-in EF for code-first data evolution.
For what was of my initial question, the answer lies in removing the schema generation/validation. It is only then that manually editing the code and database may work.
UPDATE :
EF 5.0 now support migrations
I know this has been marked as solved but in my case it didn't do the trick.
Once I deleted dbo.EdmMetadata I was getting a different error:
Model compatibility cannot be checked because the database does not contain model metadata. Ensure that IncludeMetadataConvention has been added to the DbModelBuilder conventions.
The way it worked for me was to remove the Initializer class from Application_Start:
void Application_Start(object sender, EventArgs e)
{
// MyDB.SetInitializer<MyContext>(new MyInitializer());
}

Entity Framework - Foreign key constraints not added for inherited entity

It appears to me that a strange phenomenon is occurring with inherited entities (TPT) in EF4.
I have three entities.
1. Asset
2. Property
3. Activity
Property is a derived-type of Asset.
Property has many activities (many-to-many)
When modeling this in my EDMX, everything seems fine until I try to insert a new Property into the database. If the property does not contain any Activity, it works, but all hell breaks loose when I add some new activities to the new Property.
As it turns out after 2 days of crawling the web and fiddling around, I noticed that in the EF store (SSDL) some of the constraints between entities were not picked up during the update process.
Property_Activity table which links properties and activities show only
one constraint
FK_Property_Activity_Activity but
FK_Property_Activity_Property was
missing.
I knew this is an Entity Framework anomoly because when I switched the relationship in the database to:
Asset <--> Asset_Activity <--> Activity
After an update, all foreign key constraints are picked up and the save is successful, with or without activities in the new property.
Is this intended or a bug in EF?
How do I get around this problem?
Should I abandon inheritance altogether?
Not a but but a poor visual designer.
Its generally best to simply manage the Entity XML by hand.
No inheritance works well for many situations.
Basically I use the update from database in the visual designer but knowing that the designer has its quirks. I have simply used the update from database to stub out the basics of what I want. Then I go into the Entity XML my self and clean it up the way I want. Just of note Complex types are a pain with the designer. If you plan to use complex types get ready to learn your Entity XML well.

EF Forced Concurrency Checks

I have an issue with EF 4.0 that I hope someone can help with. I currently have an entity that I want to update in a last in wins fashion (i.e. ignore concurrency checks and just overwrite whats in the db with what is submitted). It seems Entity Framework not only includes the primary key of the entity in the where clause of the generated sql, but also any foreign key fields. This is annoying as it means that I don't get true last in wins semantics and need to know what value the fk field had before the update or I get a concurrency exception.
I am aware that this can be short circuited by including a foreign key field as well as the navigation property on the entity. I would like to avoid this if possible as it's not a very clean solution.
I was just wondering if there was any other way to override this behaviour? It seems like more of a bug than a feature. I have no problem with ef doing concurrency checks if I instruct it to do so but not being able to bypass concurrency completely is a bit of a hindrance as there are many valid scenarios where this is not needed
I am not 100% sure this will work, but I was curious myself and think I might have found a solution.
What if you set the [ConcurrencyCheck] attribute on a field that is immutable (in my case I used the ID (Primary Key). Since that will never be changed it will never trigger a concurrency exception and therefore clobber your entry.
Give it a whirl and see if that solves your issue.