efcore: scaffolding existing mature db leaves an endless list of model "corrections" - tooling hell & monkey code ... solutions?

I have a large mature database that has been paired with EF 6.4 for years. All relationships properly defined, EF 6.4 was happy and allowed me to utilize the benefits of EF. Never ever had to dig into the bowels of EF and I was glad for the black box experience.

In a different (new framework) application I am using the same database for a NET5.0 Web Api together with EF Core 5.01. I was hoping for the same black box experience, but so far it has been an outright hell with cryptic error messages, endless hours of monkey code , and at least one seemingly unsolvable problem. Wasted weeks of trying different things and made no progress.

This db contains 115 tables, apparently scaffolding cannot determine what the primary keys are in these tables, so I am monkey coding [Key] and “using System.ComponentModel.DataAnnotations;” 115 times over!

Is there a setting I can use so the scaffolding recognizes and put these two items in the correct place for me?

Second, a table called Client has several dependent lookup tables with one-to-many relationships. SSMS shows a nice diagram with keys and many symbols in all the right places, and EF 6.4 was happy! One of the lookup tables is called Gender.

public partial class EqGender
    {
        public EqGender()
        {
            Clients = new HashSet<Client>();
        }

        public int GId { get; set; }
        public string Gender { get; set; }

        public virtual ICollection<Client> Clients { get; set; }
    }`


public partial class Client
    {
        public Client()
        {
            Appointments = new HashSet<Appointment>();
            ...
            Transactions = new HashSet<Transaction>();
        }

        [Key] public int ClientId { get; set; }
        public string Cname { get; set; }
        public string Cdescription { get; set; }
        public int? OwnerLocationId { get; set; }
        public int? EnteredByProviderId { get; set; }
        public int? OwnerBillToId { get; set; }
        public bool? BillLocation { get; set; }

        public int? BId { get; set; }
        public virtual EqGender GIdNavigation { get; set; }
        
        [ForeignKey("EnteredByProviderId")] public virtual Provider EnteredByProvider { get; set; }
        [ForeignKey("OwnerBillToId")]  public virtual Owner OwnerBillTo { get; set; }
        [ForeignKey("OwnerLocationId")] public virtual Owner OwnerLocation { get; set; }
        
        public virtual ICollection<Appointment> Appointments { get; set; }
        public virtual ICollection<Transaction> Transactions { get; set; }
    }

When I query for Client, I get " Microsoft.Data.SqlClient.SqlException (0x80131904): Invalid column name ‘BIdNavigationBId’."

As far as I can see these two Entities are properly setup as per the documentation. What is wrong here?

And I don’t even know if this is the last problem I can expect to have to deal with.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 16 (12 by maintainers)

Most upvoted comments

Yup, I did indeed create appDbContext after the scaffolding. Using HttpRepl I was able to see that some of my controller actions were indeed producing the desired results, but not all… at that time I was thinking there were some issues that I did not know how to fix just yet. Posted to ASPNET forums, but that never had a chance without someone looking at my code. Never went back to a earlier decision point (create appDbContext) and reevaluated my options at that point. The types of exception messages I was getting and the feedback at ASPNET forums were pointing me towards Model customizations. I.e. one rabbit hole after the other.

I do end up on doc.microsoft.com from time to time to find solutions to problems I run into, but I never go there to prepare for an implementation. Usually I get lost in lingo overload, so it is not my first choice. Most of the time I do not know the right terminology to be successful in searching, or the terminology changed to better reflect current thinking (at Microsoft). Looking at this again and I must say this page clearly spells out “The scaffolded DbContext class name will be the name of the database suffixed with Context by default.”

Just never got to that point.

I do go to YouTube, but I find the examples mostly of the Books/Authors Students/Classes kind. For visual learners a full walk-through is very helpful, almost essential. Not only do these show how it is done, but also the terminology gets highlighted.

I am appreciative of the help I got, and as a result I have made some good progress since, even with that brown paper bag on my head with the word SHAME written on it.

This ended up being the result of creating a new DbContext without model configuration rather than using the scaffolded one.

Look at the docs for “dotnet ef dbcontext scaffold”

And in order to help, you must share a repro project.

@wvmstr there’s really nothing we can do without the database schema. If possible, please send a ZIP file to my email address (visible on my github profile).

If you opt in for DataAnnotations, Key annotation is always scaffolded, actually.

~@anranruye~ @wvmstr we generally need to see a very concrete issue, including the database schema being scaffolded and the resulting model.

For your first issue, note that EF Core doesn’t scaffold the [Key] where that isn’t necessary; EF Core automatically detects key properties by convention if they’re called Id or <Class>Id (see the docs). If those are the properties being scaffolded, then there’s no need for you to go over it and add the attribute. Otherwise, can you please post a sample table (i.e. a CREATE TABLE statement) which doesn’t scaffold correctly for you?

For your second question, we’re really lacking the necessary information to investigate. I recommend you open a separate issue (and keep this one for the first problem), and please include a runnable code sample.