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

Decide on which constructor to call by convention #10852

Closed
ajcvickers opened this issue Feb 1, 2018 · 3 comments
Closed

Decide on which constructor to call by convention #10852

ajcvickers opened this issue Feb 1, 2018 · 3 comments
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-enhancement
Milestone

Comments

@ajcvickers
Copy link
Contributor

EF may be able to call several of the constructors defined on an entity type. By convention, we should always choose the one with the most number of services that can map--similar to D.I. However, when mapping scalar properties, we could:

  • Call the parameterless constructor (or the constructor with only services) if it is available. This would avoid any breaking change because this is the kind of constructor EF has always called.
  • Call the constructor with the most scalar properties that match. The reasoning for this is that if a constructor that matches has been defined, then it could very well be intended that we call it. However, it may do extra validation or other things that are not needed/slow/harmful if called by EF

Note that if only one constructor is defined, then EF will use it--this is just about the case when multiple are defined.

@ajcvickers ajcvickers self-assigned this Feb 3, 2018
@ajcvickers ajcvickers added this to the 2.1.0 milestone Feb 3, 2018
@ajcvickers
Copy link
Contributor Author

Initial decision: for scalar properties, match zero by default (avoids breaking change) then fewest to most (avoids ignoring field mapping configuration) and change using fluent API/annotations when available. Also, file an issue to consider changing this in the next breaking release.

ajcvickers added a commit that referenced this issue Feb 21, 2018
Issue #10852

Now we pick the constructors with the most number of services, followed by the constructor with the least number of regular properties.
@ajcvickers ajcvickers added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Feb 22, 2018
ajcvickers added a commit that referenced this issue Feb 23, 2018
Issue #10852

Now we pick the constructors with the most number of services, followed by the constructor with the least number of regular properties.
@vanillajonathan
Copy link
Contributor

It could also try to find a constructor by visibility, so that it first looks for a private constructor. So that a entity could be designed with a private constructor for use by EF, and a public constructor for use by developers for creating a new instance of the class.

I have to work around this using a a public static method together with a private constructor.

public class Blog
{
    private HashSet<Post> _posts = null!;

    // Private constructor for Entity Framework
    private Blog(int blogId, string url)
    {
        BlogId = blogId;
        Url = url;
    }

    public int BlogId { get; private set; }
    public string Url { get; private set; }
    public IReadOnlyCollection<Post> Posts => _posts.ToList().AsReadOnly();

    // Static method to create an instance with _posts set to empty instead of null.
    public static Blog Create(int blogId, string url)
    {
        var blog = new Blog(blogId, url);
        blog._posts = new HashSet<Post>();
        
        return blog;
    }
}

@ajcvickers ajcvickers modified the milestones: 2.1.0-preview2, 2.1.0 Nov 11, 2019
@weitzhandler
Copy link
Contributor

weitzhandler commented Nov 22, 2019

I'm facing a similar issue related to readonly-properties. I'm using EF Core 3.

I'm trying to use readonly properties by taking advantage of constructors.
But in the other hand, I need to define a parameterless constructor as well.

Here's an example:

public class Contact
{
  public Contact() { }
  public Contact(string name) 
  {
    Name = name;
  }
   public string Name { get; }
}

When loading Contacts from store, EF uses the parameterless constructor instead of the other one that takes the property values.

Note: I've explicitly included the Name property in my model in the OnModelCreating routine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-enhancement
Projects
None yet
Development

No branches or pull requests

3 participants