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

Support complex properties on Owned types #33170

Open
Tracked by #31238
lzoller-flexibilIT opened this issue Feb 27, 2024 · 4 comments
Open
Tracked by #31238

Support complex properties on Owned types #33170

lzoller-flexibilIT opened this issue Feb 27, 2024 · 4 comments

Comments

@lzoller-flexibilIT
Copy link

File a bug

I'm trying to set up a database containing different tables that have to be implemented as ComplexType or Owned respectively. I'm using attributes to configure that.

The ef command line tool succussfully creates a migration for the model but the generated code contains errors for every occurence of a ComplexType within an Owned type because the class OwnedNavigationBuilder doesn't contain a method for ComplexType.

I can't make everything Owned because of missing relations and I can't make everything ComplexType because of a 1:n relation from another table.

As the ef tool successfully generates the migration code and accepts the model this must be a bug in EFcore.
The migration code generated keeps the project from building so e.g. ef migrations remove will fail, the migration classes have to be removed manually.

Include your code

Here the relevant snippets from the model.

Starting point is the Invoice class containing a list of LineItems:

    public class Invoice
    {
        public Company customer { get; set; }
        public Project project { get; set; }
        ...
        public List<LineItem> line_items { get; set; }
    }

The LineItem is Owned and contains a Proposition:

    [Owned]
    public class LineItem
    {
        public string? LineItemType { get; set; }
        public string? Name { get; set; }
        public string? Description { get; set; }
        ...
        public Proposition Proposition { get; set; }
    }

Finally the Proposition is a ComplexType:

    [ComplexType]
    public class Proposition
    {
        public string? Type { get; set; }
        public int? Id { get; set; }
        public string? Name { get; set; }
        ...
    }

Creating a migration based on this model via...

dotnet ef migrations add Initial

...is successful:

Build started...
Build succeeded.
Done. To undo this action, use 'ef migrations remove'

Include stack traces

(no execution possible)

Include verbose output

The migration classes produced looks like this (the complier error occurs at b1.ComplexProperty<>):

            ...
            modelBuilder.Entity("MyProject.Model.Invoice", b =>
                {
                    ...
                    b.HasOne("PapierkramShared.Model.Company", "customer")
                        .WithMany()
                        .HasForeignKey("customerId")
                        .OnDelete(DeleteBehavior.Cascade)
                        .IsRequired();

                    b.HasOne("PapierkramShared.Model.Project", "project")
                        .WithMany()
                        .HasForeignKey("projectId")
                        .OnDelete(DeleteBehavior.Cascade)
                        .IsRequired();

                    b.OwnsMany("MyProject.Model.LineItem", "line_items", b1 =>
                        {
                            ...
                            b1.Property<string>("LineItemType")
                                .HasColumnType("nvarchar(max)")
                            b1.Property<string>("Name")
                                .HasColumnType("nvarchar(max)")
                            b1.Property<string>("Description")
                                .HasColumnType("nvarchar(max)")
                            ...
                            b1.ComplexProperty<Dictionary<string, object>>("Proposition", "MyProject.Model.InvoiceDetails.line_items#LineItem.Proposition#Proposition", b2 =>
                                {
                                    b2.IsRequired();
                                    b2.Property<string>("Type")
                                        .IsRequired()
                                        .HasColumnType("nvarchar(max)")
                                    b2.Property<int>("Id")
                                        .HasColumnType("int")
                                    b2.Property<string>("Name")
                                        .IsRequired()
                                        .HasColumnType("nvarchar(max)")
                                    ...

The compiler error produces is this one (translated from German):
error CS1061: "OwnedNavigationBuilder" does not contain a definition for "ComplexProperty" and no accessible extension method "ComplexProperty" accepting a first argument of type "OwnedNavigationBuilder" could be found.

Include provider and version information

EF Core version: 8.0.2
EF Core Command-line Tools: 8.0.2
Database provider: Microsoft.EntityFrameworkCore.SqlServer / also tried: Npgsql.EntityFrameworkCore.PostgreSQL
Target framework: NET 8.0
Operating system: Windows 11
IDE: Visual Studio 2022 17.9.0

@JoasE
Copy link

JoasE commented Feb 27, 2024

I was about to create this issue myself! However, I was going to make it a feature request as I was using the fluent api to configure my entity relations and noticed the ComplexProperty builder method missing on the OwnedNavigationBuilder.

Should I create a separate issue for this? As the fact that the migrations generator is generating code that has a compile time error is an issue of itself, but it could be fixed by implementing functionality.

My code:

public class Entity
{
    public int Id { get; set; }

    public OwnedEntity OwnedEntity { get; set; }

    public ComplexType ComplexType { get; set; }
}

public class OwnedEntity
{
    public int Id { get; set; }

    public ComplexType ComplexType { get; set; }
}

public class ComplexType
{
    public string Name { get; set; }

    public string Description { get; set; }
}

class TestDbContext : DbContext
{
    public TestDbContext() : base(new DbContextOptionsBuilder<TestDbContext>().UseSqlServer().Options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Entity>(cfg =>
        {
            cfg.ComplexProperty(x => x.ComplexType);

            cfg.OwnsOne(x => x.OwnedEntity, cfg =>
            {
                // Method to configure ComplexProperty does not exist!
                cfg.ComplexProperty(x => x.ComplexType); // Error CS1061  'OwnedNavigationBuilder<Entity, OwnedEntity>' does not contain a definition for 'ComplexProperty' and no accessible extension method 'ComplexProperty' accepting a first argument of type 'OwnedNavigationBuilder<Entity, OwnedEntity>' could be found
            });
        });
    }
}

@lzoller-flexibilIT
Copy link
Author

Hi @JoasE, that's curious :-)
Creating your own issue sounds good.
Thanks for hint with the fluent api and the sample code - even though I was trying to prevent using it...

@ajcvickers
Copy link
Contributor

@AndriySvyryd Do you know if we are already tracking this?

@AndriySvyryd
Copy link
Member

It looks like I missed creating an issue for this

@AndriySvyryd AndriySvyryd changed the title unable to use a ComplexType in an Owned type Support complex properties on Owned types Feb 28, 2024
@ajcvickers ajcvickers added this to the Backlog milestone Mar 7, 2024
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

4 participants