Search code examples
c#sql-serverentity-framework-corerazor-pagesdata-annotations

System.ComponentModel.DataAnnotations 2023


What's changed? I've had this C# Razor app (SQL backend) developed and deployed in production for 3 years now. Recently, I've added 3 new tables in SQL and rather than use Package Manager console to add a migration, I just manually edited the existing DBContext class to add three new DbSets...

  public virtual DbSet<PaymentPlan> oDbSetPmtPlan { get; set; }  

added three new classes in my Models directory, and edited an existing razor page that needs to get data from the new tables. My local DB is a copy of the production. Every time I ran my project I kept getting an invalid object error when trying to open the page referencing one of the new tables.

public IList<Models.PaymentPlan> OPmtPlansList { get; set; }
.
.
.
public async Task<IActionResult> OnGetAsync(string id)
{
.
.
OPmtPlansList = await _dbWriterContext.oDbSetPmtPlan.Where(m => m.ToBalance <= TotalBalanceDue).ToListAsync();

I finally got it to work after adding this markup in the PaymentPlan class, [Table("{Name of table in SQL Server")].

namespace Customer_BlahBlah.Models
{
    [Table("PaymentPlan")]
    public partial class PaymentPlan
    {
        [Key]
        public Guid PlanId { get; set; }

I don't get it. My other existing classes never had this markup and continue to work, ie CRUD. There's nothing different in the way I designed my new tables in SSMS. I compared everything. Debug stepped through everything and it's just not making any sense.

These are the versions I'm currently using in my project...

Id                                                   Versions    ProjectName    
--                                                   --------    -----------    
Microsoft.Extensions.Configuration.UserSecrets       {6.0.1}     Customer Blah
IBM.Data.DB2.Core                                    {3.1.0.600} Customer Blah
Microsoft.VisualStudio.Web.CodeGeneration.Design     {5.0.2}     Customer Blah
MailKit                                              {3.3.0}     Customer Blah
Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation    {6.0.8}     Customer Blah
Microsoft.EntityFrameworkCore                        {6.0.8}     Customer Blah
Microsoft.EntityFrameworkCore.SqlServer              {6.0.8}     Customer Blah
System.Linq.Dynamic.Core                             {1.2.19}    Customer Blah
Microsoft.CodeAnalysis.CSharp.Workspaces             {4.2.0}     Customer Blah
EntityFramework.IBM.DB2                              {6.4.1}     Customer Blah
Microsoft.AspNetCore.Identity.EntityFrameworkCore    {6.0.8}     Customer Blah
Net.IBM.Data.Db2                                     {6.0.0.200} Customer Blah
EntityFramework                                      {6.4.4}     Customer Blah
Microsoft.EntityFrameworkCore.Relational             {6.0.8}     Customer Blah
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore {6.0.8}     Customer Blah
Microsoft.AspNetCore.Identity.UI                     {6.0.8}     Customer Blah
MimeKit                                              {3.4.0}     Customer Blah
Microsoft.EntityFrameworkCore.Tools                  {6.0.8}     Customer Blah
IBM.EntityFrameworkCore                              {6.0.0.200} Customer Blah

16 have updates pending but, I'm holding off on the updates until I get a better understanding of what's going on currently with this weird issue.

Edited to add the script to create the table mentioned above.

CREATE TABLE [dbo].[PaymentPlan](
    [PlanId] [int] IDENTITY(1,1) NOT NULL,
    [FromBalance] [numeric](6, 2) NOT NULL,
    [ToBalance] [numeric](6, 2) NOT NULL,
    [MaxMonthsLimit] [int] NOT NULL,
 CONSTRAINT [PK_PaymentPlan] PRIMARY KEY CLUSTERED 
(
    [PlanId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'The Plan Unique Identifier' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'PaymentPlan', @level2type=N'COLUMN',@level2name=N'PlanId'
GO

Solution

  • According to the code you posted, your DbSet name: oDbSetPmtPlan does not match that of the SQL Server table: PaymentPlan. EF Core will look for a table named after the DbSet property (not its generic type) unless you use DataAnnotations or Fluent API to configure a different table name (as you eventually did).

    This has always been the convention that EF Core works to. Nothing has changed.

    https://learn.microsoft.com/en-us/ef/core/modeling/entity-types?tabs=data-annotations#table-name