.NET Core 3.1升级后EF Core拥有实体关系异常求助
Alright, let's break down what's causing these errors after upgrading to .NET Core 3.1 and fix them step by step.
First, let's unpack the core issues:
- EF Core 3.1 Convention Misinterpretation: Even though you never explicitly configured
Portfolioas an owned entity, EF Core's default conventions are mistakenly treating it as an owned entity ofBill. This happens because it couldn't properly resolve the foreign key relationship betweenBillandPortfolioon its own. Owned entities can't act as the principal side of a non-ownership relationship, which throws your first error. - Class Name Typo: You've defined a class named
SampleItems, but yourPortfoliousesList<SampleItem>for its navigation property. This mismatch is confusing EF and would cause compilation issues even before hitting runtime errors. - Misplaced Relationship Configuration: When you tried to use
OwnsManyforPortfolio.SampleItems, EF already thoughtPortfoliowas an owned entity—so it threw a conflict error because an entity can't be both owned and non-owned.
1. Fix the Class Name Typo
First, rename your SampleItems class to SampleItem (singular, matching the navigation property in Portfolio), and add a foreign key property to explicitly link it to Portfolio:
public class SampleItem { [Key] public Guid Id { get; set; } public string Code { get; set; } public string Type { get; set; } // Add foreign key to establish relationship with Portfolio public Guid PortfolioId { get; set; } public virtual Portfolio Portfolio { get; set; } }
2. Explicitly Configure Bill ↔ Portfolio Relationship
In your OnModelCreating method, tell EF Core explicitly that Portfolio is an independent principal entity, not an owned entity of Bill. This overrides the incorrect convention-based assumption:
protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.ApplyConfiguration(new IntegrationEventLogEntityTypeConfiguration()); var status = BillStatus.Pending.ToString(); modelBuilder.Entity<Bill>().Property(lst => lst.Created).HasDefaultValueSql("getdate()"); modelBuilder.Entity<Bill>() .Property(p => p.Status) .HasDefaultValue("Pending"); modelBuilder.Entity<LivingExpenseSetting>(); // Define the Bill ↔ Portfolio relationship clearly modelBuilder.Entity<Bill>() .HasOne(b => b.Portfolio) // One Bill links to one Portfolio .WithMany() // One Portfolio can have many Bills (use .WithOne() if it's a 1:1 relationship) .HasForeignKey(b => b.PortfolioId) .OnDelete(DeleteBehavior.Restrict); // Adjust delete behavior to match your business logic // Define Portfolio ↔ SampleItem one-to-many relationship modelBuilder.Entity<Portfolio>() .HasMany(p => p.SampleItems) // One Portfolio has many SampleItems .WithOne(s => s.Portfolio) // Each SampleItem belongs to one Portfolio .HasForeignKey(s => s.PortfolioId) .OnDelete(DeleteBehavior.Cascade); // Adjust delete behavior as needed }
3. Remove Redundant NotMapped Property
The Sample property in Portfolio is just a wrapper for SampleItems and doesn't add any value—plus it could confuse EF's relationship discovery. Delete it:
public class Portfolio { [Required] public Guid Id { get; set; } public virtual List<SampleItem> SampleItems { get; set; } // Remove this redundant property // [NotMapped] // public List<SampleItem> Sample{ get{ return SampleItems; } } }
4. Add SampleItem DbSet (Optional but Recommended)
If you need to directly query or modify SampleItem entries, add its DbSet to your RepositoryContext:
public virtual DbSet<SampleItem> SampleItems { get; set; }
- By explicitly defining the
Bill↔Portfoliorelationship, we're telling EF Core thatPortfoliois a standalone entity, not an owned part ofBill—fixing the first error. - Configuring the
Portfolio↔SampleItemrelationship properly replaces the incorrectOwnsManyattempt (sinceSampleItemshould be a regular dependent entity, not an owned one). - Fixing the class name and removing redundant code eliminates confusion for EF's relationship discovery system.
内容的提问来源于stack exchange,提问作者Mamatha Yaramati

