Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EF Core 8 + MVVM - ObservableCollection<string> gives errors in TPC #30459

Closed
DJRM2021 opened this issue Mar 12, 2023 · 5 comments
Closed

EF Core 8 + MVVM - ObservableCollection<string> gives errors in TPC #30459

DJRM2021 opened this issue Mar 12, 2023 · 5 comments

Comments

@DJRM2021
Copy link

I am using EF Core 8 Preview 1.2 and CommunityToolkit.Mvvm 8.1.0 in a WASDK 1.2/WinUI 3 C# desktop app project.

Here are my models:

public abstract partial class Person : ObservableObject
{
    [ObservableProperty][Key] int personId;
    [ObservableProperty] string name;
}
public partial class Employee : Person
{
    [ObservableProperty] string employeeId;
    [ObservableProperty] string department;
}
public partial class Teacher : Employee
{
    [ObservableProperty] string teacherId;
    [ObservableProperty] ObservableCollection<string> competencies;
}

Here is my DbContext:

public class PersonDbContext : DbContext
{
    public DbSet<Person> Person { get; set; }
    public DbSet<Employee> Employee { get; set; }
    public DbSet<Teacher> Teacher { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Person>().UseTpcMappingStrategy();
    }
}

Here is the error when running Add-Migration in the PM console:

PM> Add-Migration D Build started... Build succeeded.

Unable to create a 'DbContext' of type ''. The exception 'The entity type 'ObservableCollection' requires a primary key to be defined. If you intended to use a keyless entity type, call 'HasNoKey' in 'OnModelCreating'. For more information on keyless entity types, see https://go.microsoft.com/fwlink/?linkid=2141943.' was thrown while attempting to create an instance. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728

Error is not supposed to occur because Teacher inherits from Employee which inherits from Person. Person base class has the [Key] annotation which tells EF core which primary key to use. Am I missing something here? The project compiles without any errors. It's the migration that fails.

I am using Visual Studio Community Edition 17.5.1

The following NuGet packages are installed:
Microsoft.EntityFrameworkCore.SqlServer 8.0.0-preview.1.23111.4
Microsoft.EntityFrameworkCore.Tools 8.0.0-preview.1.23111.4
Microsoft.EntityFrameworkCore.Design 8.0.0-preview.1.23111.4
CommunityToolkit.Mvvm 8.1.0

@ajcvickers
Copy link
Member

This issue is lacking enough information for us to be able to fully understand what is happening. Please attach a small, runnable project or post a small, runnable code listing that reproduces what you are seeing so that we can investigate.

@DJRM2021
Copy link
Author

DJRM2021 commented Mar 13, 2023

Repro Steps:

  1. Create a C# project in VS 2022, using this template:
    image
  2. Install the following NuGet packages
    Microsoft.EntityFrameworkCore.SqlServer 8.0.0-preview.1.23111.4
    Microsoft.EntityFrameworkCore.Tools 8.0.0-preview.1.23111.4
    Microsoft.EntityFrameworkCore.Design 8.0.0-preview.1.23111.4
    CommunityToolkit.Mvvm 8.1.0
  3. Update the following NuGet packages
    Microsoft.Windows.SDK.BuildTools
    Microsoft.Windows.AppSDK
  4. Add a file and name it "Person.cs" in the project.
    image
  5. Inside the "Person.cs" file, define 3 classes, Person (abstract), Employee (inherit Person) and Teacher (inherit Employee)
using CommunityToolkit.Mvvm.ComponentModel;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;

namespace App2
{
    public abstract partial class Person : ObservableObject
    {
        [ObservableProperty][Key] int personId;
        [ObservableProperty] string name;
    }
    public partial class Employee : Person
    {
        [ObservableProperty] string employeeId;
        [ObservableProperty] string department;
    }
    public partial class Teacher : Employee
    {
        [ObservableProperty] string teacherId;
        [ObservableProperty] ObservableCollection<string> competencies;
    }
}
  1. Add a new file and name it "PersonDbContext.cs"
using Microsoft.EntityFrameworkCore;

namespace App2
{
    public class PersonDbContext : DbContext
    {
        public DbSet<Person> Person { get; set; }
        public DbSet<Employee> Employee { get; set; }
        public DbSet<Teacher> Teacher { get; set; }
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(@"Server=MyServer;Database=Person;TrustServerCertificate=True;Integrated Security=True");
        }
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Person>().UseTpcMappingStrategy();
        }
    }
}
  1. Build the project. There should be no compiler errors/warnings.
  2. Open the Package Manager Console window and enter Add-Migration myMigration, the error should appear.
    image

@DJRM2021
Copy link
Author

This issue is lacking enough information for us to be able to fully understand what is happening. Please attach a small, runnable project or post a small, runnable code listing that reproduces what you are seeing so that we can investigate.

I've added the repro steps in the comments, thank you.

@ajcvickers
Copy link
Member

@DJRM2021 Collections of primitive types are not yet supported by convention--see #25163 and #29427. You can use a value converter for this, as documented here:

For example: https://learn.microsoft.com/en-us/ef/core/modeling/value-conversions?tabs=data-annotations#examples

modelBuilder.Entity<Teacher>().Property(e => e.Competencies).HasConversion(
    v => JsonSerializer.Serialize(v, (JsonSerializerOptions)null),
    v => JsonSerializer.Deserialize<ObservableCollection<string>>(v, (JsonSerializerOptions)null),
    new ValueComparer<ObservableCollection<string>>(
        (c1, c2) => c1.SequenceEqual(c2),
        c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode())),
        c => new ObservableCollection<string>(c)));

@DJRM2021
Copy link
Author

@ajcvickers Thanks for the prompt reply and assistance. I'm hoping support for collections of objects will be added in EF Core 8.

@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Mar 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants