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

Allow navigations and FK properties on non-collection complex types #31245

Open
Tracked by #31238
AndriySvyryd opened this issue Jul 12, 2023 · 11 comments
Open
Tracked by #31238

Allow navigations and FK properties on non-collection complex types #31245

AndriySvyryd opened this issue Jul 12, 2023 · 11 comments

Comments

@AndriySvyryd
Copy link
Member

The relationship itself will still be defined between two entity types.

Depends on #31236

@roji
Copy link
Member

roji commented Jan 18, 2024

Adding needs-design as I believe we should allow (outgoing) navigations from complex types even when nested inside a collection.

@vgallegob
Copy link

vgallegob commented May 26, 2024

Hello team,

I also need this feature. I am starting to adopt Complex Types in my domain, and I find it limiting not beeing able to have FKs inside of them.

Here's a very simple example;

public abstract class UserActivityEntity : UserEntity
{
    public DateTime CreatedAt { get; set; }
    public required string CreatedByUserId { get; set; }
    public virtual AppUser? CreatedByUserNav { get; set; }

    public DateTime UpdatedAt { get; set; }
    public required string UpdatedByUserId { get; set; }
    public virtual AppUser? UpdatedByUserNav { get; set; }
}

could become

public class UserActivityCT
{
    public DateTime At { get; set; }
    public required string ByUserId { get; set; }
    public virtual AppUser? ByUserNav { get; set; }
}

public abstract class UserActivityEntity : UserEntity
{
    public UserActivityCT Created { get; set; }
    public UserActivityCT Updated { get; set; }
}

But currently I get this error:

Unable to create a 'DbContext' of type ''. The exception 'The expression 'l => l.Created.ByUserNav' is not a valid member access expression. The expression should represent a simple property or field access: 't => t.MyProperty'. (Parameter 'memberAccessExpression')' was thrown while attempting to create an instance. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728

And so on and so on...

This is a small example but you can see the potential benefits of it. This way I could enforce domain rules much more easyly.

At the end of the day, it's just another column in the DataBase, so technicallities aside it would make sense to be able to do that, I think.

Is there any work around you can think of? Is this planned for .NET 9?

@roji
Copy link
Member

roji commented May 26, 2024

@vgallegob you should already be able to use owned entities to map the above; this issue is specifically about allowing navigations on complex types, which are a new mapping strategy (we don't yet know if we'll be able to deliver this for 9.0). If you're having trouble with owned entities, please open a new issue with a runnable, minimal code sample.

@vgallegob
Copy link

vgallegob commented May 27, 2024

I am already using Complex Types in my app. Would be nice to have it unified in Complex Types. For now I'll do this ones that have a FK with owned entities.

Thanks Shay!

@CesarD
Copy link

CesarD commented Aug 7, 2024

This deserves more upvotes!
I want to leverage ComplexTypes for Value Objects in my projects but not possible since I cannot do something as simple as having an Address VO that holds a reference to a Country entity and its corresponding CountryId.

@adrielairaldo
Copy link

@vgallegob Beautiful use case you have put forward!

I just wanted to ask you why you said:

At the end of the day, it's just another column in the DataBase

Your Value Object UserActivityCT will already be represented by two columns in your UserActivityEntity (one for At and one for ByUserId), so, I understand that what we want is to generate a FK from Created.ByUserId to User.Id. If I understand your case correctly, no new columns are needed.

In fact, a syntax like the one that already exists would be great (but it doesn't work):

builder.HasOne<User>().WithMany().HasForeignKey(uae => uae.Created.ByUserId).IsRequired(); where (uae is UserActivityEntity)

Finally, my analysis must also be applied to the Updated field.

@AndriySvyryd
Copy link
Member Author

@CesarD Why do you need to map Address as a complex type instead of an owned type?

@CesarD
Copy link

CesarD commented Nov 1, 2024

@AndriySvyryd because of the features ComplexTypes provide? Like being able to really use Records instead of mimicking them with classes and prevent having to track them as entities as it's the case of Owned Entities.

@AndriySvyryd
Copy link
Member Author

Ok, then #11457 could be an alternative way of supporting your scenario.

@CesarD
Copy link

CesarD commented Nov 1, 2024

Not sure about that. I'm looking to have support more closely to Value Objects rather than yet another type of entity.
Address would be a VO and because of that, it shouldn't be tracked like an entity.

@vgallegob
Copy link

All we want is a unified developer experience that allows mapping Value Objects in the DB. Navigation properties need to be represented in this unified way too, for convenience.

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

6 participants