1

I'm writing a IQueryable<T> extension method and I would like to get the foreign keys of the navigation properties of T. I have figured out that I can get access to them through IModel.FindEntityType(T).GetNavigations(), the question is how to best get access to the IModel while keeping the method as simple as possible.

At the moment the method looks something like this:

public static IQueryable<TQuery> DoMagic<TQuery>(this IQueryable<TQuery> query, IModel model)
{
    var entity = model.FindEntityType(entityType);
    var navigationProperties = entity.GetNavigations();

    ...
}

I would love if I wouldn't need to pass IModel as an argument like this:

public static IQueryable<TQuery> DoMagic<TQuery>(this IQueryable<TQuery> query)
{
    var entity = Model.FindEntityType(entityType);
    var navigationProperties = entity.GetNavigations();

    ...
}

I have considered adding a IServiceCollection extension method and passing the DbContext and setting IModel as a static property to the IQueryable<T> extension method. The problem with that is that it is limiting me to one DbContext.

I have also looked into the option to add a extension method to DbContextOptionsBuilder but haven't really figured out best way to achieve what I want to do this way.

Maybe there is other ways to get access to the foreign keys? Any help is greatly appreciated!

Edit

From the navigation properties I want to access the ForeignKey-property to know what property is used to resolve the navigation property. Something like:

navigationProperties.ToList().Select(x => x.ForeignKey);
Ganhammar
  • 1,871
  • 1
  • 16
  • 29

1 Answers1

1

One way of getting the navigation properties:

public static IQueryable<TQuery> DoMagic<TQuery>(this IQueryable<TQuery> query)
{
    var navigationProperties = typeof(TQuery).GetProperties()
        .Where(p => (typeof(IEnumerable).IsAssignableFrom(p.PropertyType) && p.PropertyType != typeof(string)))
        .ToArray();

    ...
}

UPDATE: Trying to get DbContext which has the Model property from IQueryable would result in some not pretty code, this link shows how it could be done:

.Net EF Core 2.1 Get DbContext from IQueryable argument

If you are using dependency injection, you could put the instance of DbContext into the container in the scope of the web request or the operation and inject it into the class with the DoMagic method.

Another way could to add the method to the descendant of DbContext class, then the model parametere would not be needed.

Martin Staufcik
  • 8,295
  • 4
  • 44
  • 63
  • Thanks! The problem with that solution is that it doesn't give me the Foreign Keys, only the navigation propertie, I should probably have clarified that more. – Ganhammar Mar 28 '20 at 07:46
  • Updated the question to clarify that. – Ganhammar Mar 28 '20 at 07:53
  • Yeah, I passed by that question a couple of times and yes, some not pretty code I agree with Just wanted to see if there was some solution that I'm missing. I guess I just need to accept that there is no perfect solution and pick one of the lesser evils! Thanks! – Ganhammar Mar 28 '20 at 08:26