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 mapping to interfaces with polymorphic associations #757

Open
Tracked by #240
ajcvickers opened this issue Oct 1, 2014 · 7 comments
Open
Tracked by #240

Allow mapping to interfaces with polymorphic associations #757

ajcvickers opened this issue Oct 1, 2014 · 7 comments

Comments

@ajcvickers
Copy link
Member

Consider scenario described in #1489 when looking at this

@glen-84
Copy link

glen-84 commented May 28, 2015

This would really help in enabling the scenario described here.

Following on from that example, the forum may have a "Topic" entity with an associated ApplicationUser. Since the ApplicationUser is in the consuming web application (and can not be referenced by the module), the solution would be to use a common interface like IUser/IApplicationUser/IIdentityUser (or similar) to define the relationship.

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

    // By interface.
    public virtual IUser User { get; set; }

    // By class.
    public virtual AnotherAssociatedEntity Entity { get; set; }
}

I like the idea by @ravensorb in #1489. Perhaps the delegate could also receive some form of context that could provide access to attributes on the property, for example.

EF Core is a rewrite/large refactoring in many places, so now might be the best time to make something like this happen (or at least prepare for it).

@Jabronironi
Copy link

Currently, we are getting around this limitation by using a combination of expression trees (to allow predicate based searching against our interfaces) and AutoMapper (to convert from our IoC factoried domain objects that are based on our interfaces to our data objects). This is getting us by, but having this feature would greatly simplify our setup. Any ideas if this is on the roadmap?

@ravensorb
Copy link

Is there any possibility of this getting prioritized?

@ajcvickers
Copy link
Member Author

@ravensorb We will consider this item when planning work for 2.2, but I can't promise anything given that there are many other high priority features with which it will be competing for resources.

@935main
Copy link

935main commented Jul 5, 2018

Does someone else saying 'Please' make a difference? I'm about to begin a migration to EFCore and this feature would suuuuure make that transition easier. Please?

@ajcvickers
Copy link
Member Author

@935main It helps, but no more than an up-vote in the issue, which currently only has three.

However, for you and others reading it would be useful to know how much complexity in the mapping is required. For example, consider a simple case like this:

public interface IComment
{
    int Id { get; set; }
}

public interface IBlog
{
    int Id { get; set; }
}

public interface IPost
{
    int Id { get; set; }
}

public class Comment : IComment
{
    public int Id { get; set; }
}

public class Blog : IBlog
{
    public int Id { get; set; }

    public ICollection<IComment> Comments { get; set; }
}

public class Post : IPost
{
    public int Id { get; set; }

    public ICollection<IComment> Comments { get; set; }
}

In this code there are three interfaces, and in each case the interface uniquely identifies the entity type. The relationships between Comment and Post would use one FK, and the relationship between Comment and Blog would use a a different FK. So there is really no fundamental difference between the model that uses interfaces and the one that uses classes, other than the use of interfaces.

However, there is some feeling on the team that there is little value in doing this, since once interfaces are supported, they are not useful unless they:

  • Can be mapped to different types of entity depending on how they are used in the model.
  • And/or can share an FK property across multiple relationships.

So, for example:

public interface IComment
{
    int Id { get; set; }
}

public interface IBlog
{
    int Id { get; set; }
}

public interface IPost
{
    int Id { get; set; }
}

public class PostComment : IComment
{
    public int Id { get; set; }
}

public class BlogComment : IComment
{
    public int Id { get; set; }
}

public class Blog : IBlog
{
    public int Id { get; set; }

    public ICollection<IComment> Comments { get; set; }
}

public class Post : IPost
{
    public int Id { get; set; }

    public ICollection<IComment> Comments { get; set; }
}

In this case, IComments related to a Blog would be of type BlogComment, while IComments related to Postwould be of typePostComment`. Is this needed?

In a nutshell, it would be very useful to know how you use interfaces in your model so we know what how much of the scope of this feature needs implementing to be useful.

@jhandel
Copy link

jhandel commented Jan 4, 2019

Using the example above, I notice you are using shadow properties for the FK back to the comment.. At least for my example (#14260 ) I specifically need to be able to query on Comments and avoid multiple nullable FKs (ie a single parentID field). I'll copy my example use case here since my case was closed as a duplicate)

I have bolded the relevant part, a pair of Indexed fields (parentId and parentDiscriminator) that make up the relationship instead of using a FK with a constraint.

Contact:

Id
ParentId
ParentDiscriminator

[the rest of the fields that make up a contact]

Customer:
Id
Fields that make up a customer
ICollection Contacts

Supplier:
Id
Fields that make up a supplier
ICollection Contacts

Partner:
Id
Fields that make up a partner
ICollection Contacts

Warehouse:
Id
Fields that make up a partner
ICollection Contacts

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

8 participants