-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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 related entities to be passed to constructor of aggregate root #12078
Comments
@andriysavin The issue here is that owned types cannot be configured using a call the top level .Entity method. This was supposed to throw in 2.1, but that change was accidentally reverted-see issue #9148. To make your code work you instead need to configure the property mapping for the owned type in each of the places it is used. For example: modelBuilder.Entity<MyEntity>(cb =>
{
cb.OwnsOne(seg => seg.Owned1).Property(e => e.MyProperty);
cb.OwnsOne(seg => seg.Owned2).Property(e => e.MyProperty);
}); |
@ajcvickers Thanks for explaining, that makes it work, though this configuration may look messy if you have many properties in the owned type - you will have to repeat the same configuration:
This can be simplified by extracting to a separate method or local function, of course, but looks not very fluent:
|
However, it's not all from me :)
I can guess that this is due to (from the docs):
What's the reason for this limitation for owned types? If I have nested owned types, does that mean that only innermost owned type will be able to use constructor injection?
|
Here is an example with nested entities which doesn't work as well with error
|
Re-opening to discuss in triage. |
Triage: moving this to the backlog as a feature request to pass related entity instances to the constructor of a parent instance, which is most useful for aggregates. See also #1985 |
Just to give a more real life example, here are some of my models (simplified).
The same model example can be considered for issue #12118 |
Any update or alternative solution for this? |
@bicatu What is the specific problem for which are you looking for an alternative solution? This issue is in the Backlog milestone. This means that it is not going to happen for the 3.0 release. We will re-assess the backlog following the 3.0 release and consider this item at that time. However, keep in mind that there are many other high priority features with which it will be competing for resources. |
I ran into the same issue even without using related entities. Found a solution for my case. Quick example: public class Event {
public Event(string subject, DateTime startDate, DateTime endDate, bool enablePrivate)
{
Subject = subject;
StartDate = startDate;
PrivateEvent = enablePrivate;
EndDate = endDate;
}
public string Subject { get; private set; }
public DateTime StartDate { get; private set; }
public DateTime EndDate { get; private set; }
public bool PrivateEvent { get; private set; }
} This gave me the following exception: So what I have found in the Microsoft docs (https://docs.microsoft.com/de-de/ef/core/modeling/constructors) : In that case the solution was to rename the parameter to "enablePrivate" and the exception was gone. |
Adding support for navigation-property via constructor is essential to accommodating C# 8.0's new nullable reference mode. modelBuilder.Entity<Workstation>()
.HasOne(w => w.Owner)
.WithMany()
.HasForeignKey("OwnerId"); class Workstation
{
public User Owner { get; set; } // CS8618 Non-nullable property 'Owner' is uninitialized.
public string Hostname { get; set; }
} class Workstation
{
public User Owner { get; set; }
public string Hostname { get; set; }
public Workstation(User owner, string hostname)
{
Owner = owner;
Hostname = hostname;
}
}
// Exception: No suitable constructor found for entity type 'Workstation'. The following constructors had parameters that could not be bound to properties of the entity type: cannot bind 'owner' in 'Workstation(User owner, string hostname)' |
@M-Pixel There is a doc page which describes how to work with NRTs in EF Core (and fix the warning): https://docs.microsoft.com/en-us/ef/core/miscellaneous/nullable-reference-types |
Having exactly the issue mentioned in the sample by @andriysavin above in a real world application. We have a nested public sealed class LatLngPoint : ValueObject<LatLngPoint>
{
private LatLngPoint(double latitude, double longitude)
{
// Argument validation...
this.Latitude = latitude;
this.Longitude = longitude;
}
public double Latitude { get; }
public double Longitude { get; }
}
public sealed class LatLngBounds : ValueObject<LatLngBounds>
{
private LatLngBounds(LatLngPoint southwest, LatLngPoint northeast)
{
this.Southwest = southwest ?? throw new ArgumentNullException(nameof(southwest), "...");
this.Northeast = northeast ?? throw new ArgumentNullException(nameof(northeast), "...");
}
public LatLngPoint Southwest { get; }
public LatLngPoint Northeast { get; }
}
public class Map : IShadowUserAuditableEntity, IAggregateRoot
{
private Map(Guid id)
{
// Argument validation...
this.Id = id;
}
public Guid Id { get; }
public LatLngBounds Viewport { get; }
}
public class MapEntityTypeConfiguration : IEntityTypeConfiguration<Map>
{
public void Configure(EntityTypeBuilder<Map> builder)
{
...
builder.OwnsOne(e => e.Viewport, builder =>
{
builder.OwnsOne(e => e.Southwest, builder =>
{
builder.Property(e => e.Latitude)
.IsRequired()
.HasColumnName("SouthwestLat");
builder.Property(e => e.Longitude)
.IsRequired()
.HasColumnName("SouthwestLng");
});
builder.OwnsOne(e => e.Northeast, builder =>
{
builder.Property(e => e.Latitude)
.IsRequired()
.HasColumnName("NortheastLat");
builder.Property(e => e.Longitude)
.IsRequired()
.HasColumnName("NortheastLng");
});
});
...
}
} Results in:
Further adding
|
Yeah I appear to be having the same issue as well. Not sure if this is thought to be resolved? I may be doing something wrong. |
This remains an issue in 5.x |
This would be a really useful feature, especially for required one-to-to or many-to-one related entities. Without this feature one could not really validate, whether the entity constructed by EF actually has the required related entity property really set (nullability might be violated)! |
issue in EF core dotnet/efcore#12078 makes things worse
My issue about this was indeed a duplicate. |
3 years and 7 months later, this remains an issue in v6.0.1. |
@ErroneousFatality As in all software development, we have limited resources and have to make hard decisions about what to prioritize. Make sure to vote (👍) for this issue if it is important to you. It currently has 18 votes, which puts it in 78th place in the list of top voted issues. See The Planning Process for more information on how we decide what to work on. |
I am trying to have an explicit many-to-many association (because implicit many-to-many associations create unwanted shadow properties): [Owned]
class PersonWorkplace {
Person RefPerson { get; } Workplace RefWorkplace { get; }
public PersonWorkpace (Person refPerson, Workplace refWorkplace) { … }} It feels like basic stuff (like WMI-style associations) does not work 😞
|
I would even say [Obsolete ("see <URL: https://github.com/dotnet/efcore/issues/12078 >")]
private Entity() { OwnedProperty = default!; } |
Note--see comments for actual issue.
Original issue:
I'm trying constructor injection feature of EF Core 2.1 RC1. Consider the following entities and DBContext configuration:
When I'm trying to add a new entity to the set, I'm getting the following exception:
What is interesting is that if I remove Owned1 or Owned2 property and all references to it, all works fine, though they are identical from configuration point of view. So its essential for this issue that at least two owned properties are present.
Further technical details
EF Core version: 2.1.0-rc1-final
Database Provider: doesn't matter, but is reproducable with InMemory and SqlServer.
IDE: Visual Studio 2017 15.7
Link to the VS solution on OneDrive: https://1drv.ms/u/s!AuaAKPMkiTEAxqgGlJX81J_GvbwIGA
The text was updated successfully, but these errors were encountered: