In another episode of Adventures with Entity Framework while migrating a legacy app…
Entity Framework Core only populated a child entity on one item in a result. To honor the 20-minute rule, and for my future self, here’s what I found:
TL;DR: You don’t need the WithOne() and HasForeignKey() when configuring the relationship.
#1. Let’s create an optional one-to-one relationship.
Let’s create a Movie and an Award table.
USEMovies;GOCREATETABLEAwards(IdINTPRIMARYKEYIDENTITY(1,1),NameNVARCHAR(100)NOTNULL);CREATETABLEMovies(IdINTPRIMARYKEYIDENTITY(1,1),NameNVARCHAR(100)NOTNULL,AwardIdINTNULL/* <-- Optional. No FK here */);GO
And now, let’s create an award, add two movies, and retrieve them to check their awards.
usingMicrosoft.EntityFrameworkCore;namespaceLookMaWhatEntityFrameworkDoes;[TestClass]publicclassMovieTests{[TestMethod]publicasyncTaskAllAwardsPlease(){conststringconnectionString=$"Server=(localdb)\\MSSQLLocalDB;Database=Movies;Trusted_Connection=True;";varoptions=newDbContextOptionsBuilder<MovieContext>().UseSqlServer(connectionString).LogTo(Console.WriteLine).Options;// 1. Let's create an "Oscar"using(varcontext=newMovieContext(options)){context.Awards.Add(newAward{Name="Oscar"});context.SaveChanges();}// 2. Let's create two movies that have won an "Oscar"using(varcontext=newMovieContext(options)){varoscar=awaitcontext.Awards.FirstOrDefaultAsync();Assert.IsNotNull(oscar);context.Movies.AddRange(newMovie{Name="Forrest Gump",AwardId=oscar.Id},newMovie{Name="Titanic",AwardId=oscar.Id});context.SaveChanges();}// 3. Let's retrieve all movies, expecting to have an Awardusing(varcontext=newMovieContext(options)){varmovies=awaitcontext.Movies// Imagine more filters here .Include(m=>m.Award)// ^^^^^// Yes, I'm including it here.ToListAsync();foreach(varmovieinmovies){Assert.IsNotNull(movie);Assert.IsNotNull(movie.Award);// ^^^^^// Assert.IsNotNull failed.// Play sad trumpet sound.}}}}
Sorry for the foreach inside the Assert. That’s not a good idea. But I’m lazy and I’m taking too long writing this.
Yes, it fails. Play sad trumpet, please. The second movie’s award isn’t populated. Arrggg!
My fault!
#4. Ignore WithOne()
Since I’m setting an unidirectional relationship, one movie/one award/multiple movies, only configuring HasOne() is enough.
Using WithOne() was telling Entity Framework Core that one award could only belong to one movie. And that’s not the case here.
publicclassMovieContext:DbContext{publicMovieContext(DbContextOptions<MovieContext>options):base(options){}protectedoverridevoidOnModelCreating(ModelBuildermodelBuilder){// Remove the entire configuration// Or, modelBuilder.Entity<Movie>().HasOne(m=>m.Award);// ^^^^^// Just this}publicDbSet<Movie>Movies{get;set;}publicDbSet<Award>Awards{get;set;}}
And since I’m following default naming conventions, I could even delete the configuration. Ahh, Cascade sets to null, which is fine here.
Yes, the right answer is to do nothing.
Et voilà!
For debugging and problem-solving tips, read Street-Smart Coding. Those two skills are more relevant now in the era of AI-assisted coding.
After rendering the component, it calls a JavaScript function that initializes the Summernote editor. Then, it registers a callback that calls a .NET function every time the editor changes to update the component state.
Notice it stores content in a MarkupString but it binds as a string.
I’ve had to change my mind about books. From chasing a book count to reading for action and pleasure.
Here are my 10 reading rules:
#1. Always be reading something. At least one page a day. Like Jim Kwik says, reading is like exercise for the brain. And when scrolling and distractions are the norm, reading is a revolution.
#2. Reading over phone time and social media. To reduce my phone time, I use books as conscious replacements. I leave books where I usually leave my phone to break the habit of scrolling.
And after a week off social media, I now read first thing in the morning instead of checking email or social media.
#3. Read two books at once. Balance non-fiction and fiction books. Non-fiction starts my mornings and fiction helps me unwind as night.
#4. Write a book recommendation. While reading a book, write a list of all books mentioned in the book. This is like climbing the inspiration tree as Austen Kleon says in Steal Like an Artist.
#5. Read actively. Write in margins, fold corners, underline, highlight. Your book marks can become a legacy. A book without marks is a book you haven’t read.
#6. Write a 10-idea list. I’m a big fan of 10-idea lists. Instead of note-taking apps, I write 10 ideas that resonate after finishing a book. It forces me to recall and remember what I read. Bonus point when paired with a 7-word summary.
#7. Reread. I’ve had to reconcile myself with rereading. It used to be a sin when I wanted to hit a large book count. The goal is to gain insight, not just hit a book number. Rereading is fine.
#8. Prefer physical books. They give you spatial clues to remember information. You might remember that an important concept is on a left-hand page, near the bottom. eBooks can’t beat that.
#9. No shame in piling books. From How to Be Rich by Ramit Seti, I learned we shouldn’t cut on things we love. I’m not cutting on books.
You’re the books you’ve read. And those you haven’t read yet. Just don’t let your books become “shelve-help.” Build a pile, go through it, then build another one.
#10. Binge-read your favorite writer. I did it when I found James Altucher for the first time. It shows you how their voice change and how your perspective expands.
Last February, I decided to write another book but in a completely different way.
I started from a validated idea. I turned my most popular personal development post, into a mini book. Instead of starting with the first words, I began with the outline, title, sales page, and cover. I wrote it backwards.
This isn’t a 7-day program or a magic formula. It’s about small daily ideas that create big change.
And as usual, here are 4 stories that resonated with me this week:
#1. I don’t use Google as my default search engine, but I still use it for email. For digital hygiene or simply for boycotting big corporations, leaving Google may improve your digital life too (7min)
#2. Hiring sucks. CVs, interviews, recruiters…But the best way to think of hiring is a two-way sales negotiation. If you’re looking for a job, here’s a piece of advice you shouldn’t miss (5min)
#3. AI is changing our job descriptions… and killing the need for junior coders. AI is splitting the dev population into expert beginners and lone wolves (8min)
#4. The next time I’m asked what superpower I’d like to have, I’d say talk to anyone in any situation. Here’s a good story from The Guardian (14min) about it.
(Bzzz…Radio voice) This email was brought to you by… 10 Surprisingly Simple Ideas That Changed My Life And Could Change Yours Too. If you’re ready to start small and see big change, check it out.