methods that are returning different return types

.net c# dynamic-linq entity-framework linq

Question

I have below methods and they are returning different entities in addition to that the input parameters going to these methods all are same and I am using those ones in where condition

   public IQueryable<LibraryEnvironment> EnvironmentFields(string spaceFunction, string category, string source)
    {
        return _dbContext.LibraryEnvironment.Where(s => s.SpaceFunction == spaceFunction
                                                                && s.Category == category &&
                                                                 s.EnvironmentSource.Name == source);
    }

    public IQueryable<LibraryEquipment> EquipmentFileds(string spaceFunction, string category, string source)
    {
        return _dbContext.LibraryEquipment.Where(s => s.SpaceFunction == spaceFunction
                                                              && s.Category == category &&
                                                               s.EquipmentSource.Name == source);
    }

    public IQueryable<LibraryLighting> LightingFields(string spaceFunction, string category, string source)
    {
        return _dbContext.LibraryLighting.Where(s => s.SpaceFunction == spaceFunction
                                                             && s.Category == category &&
                                                              s.LightingSource.Name == source);
    }

there are other methods similar to this kind as well

I am looking for a way to create the common generic method among all these methods but with a different return type and could not be able to figure it out the way. I am using .Net core with EF core

if anyone suggest any ideas on this that would be very grateful to me, thanks in advance

1
0
1/23/2020 5:23:18 PM

Accepted Answer

You can use the Set<T> method on DbContext to generically access sets. If you put all the relevant properties your filtering on into a base you can then constrain the generic parameter to that base type and still filter on all your properties.

So your classes would look something like this based on your original queries:

public class Entity
{
    public string SpaceFunction { get; set; }
    public string Category { get; set; }
}

public class LightingEquipment : Entity
{
    public LightingSource LightingSource { get; set; }
}

public class LightingSource
{
    public string Name { get; set; }
}

And your method would like this, using a source selector:

public IQueryable<T> Fields<T>(string spaceFunction, string category, string source, Func<T, string> sourceSelector) where T : Entity
{
    return _dbContext.Set<T>().Where(s => s.SpaceFunction == spaceFunction
                              && s.Category == category &&
                              sourceSelector(s) == source);
}

And you would call this method like this:

public void Consumer()
{
    var queryable = Fields<LightingEquipment>("spaceFunction", "category", "source", x => x.LightingSource.Name);
}

Docs for Set<T>()

4
1/23/2020 9:40:05 PM

Popular Answer

If you're only looking to have one method, perhaps you can get away with Generics, as @ColinM mentioned while checking the type to decide which block of code to execute.
Haven't tested it, and it could be the wrong approach. It depends a bit on where you're using it.

public T Fields<T>(string spaceFunction, string category, string source)
{
    Type tt = typeof(T);
    if(tt == typeof(IQueryable<LibraryEnvironment>))
        return _dbContext.LibraryEnvironment.Where(s => s.SpaceFunction == spaceFunction
                                                        && s.Category == category &&
                                                          s.EnvironmentSource.Name == source);
    if (tt == typeof(IQueryable<LibraryEquipment>))
        return _dbContext.LibraryEquipment.Where(s => s.SpaceFunction == spaceFunction
                                                      && s.Category == category &&
                                                        s.EquipmentSource.Name == source);
    if (tt == typeof(IQueryable<LibraryLighting>))
        return _dbContext.LibraryLighting.Where(s => s.SpaceFunction == spaceFunction
                                                      && s.Category == category &&
                                                      s.LightingSource.Name == source);
    return default;
}

You can then call the method specifying the return type:

Fields<IQueryable<LibraryEnvironment>>("a", "b", "c");
Fields<IQueryable<LibraryEquipment>>("a", "b", "c");
Fields<IQueryable<LibraryLighting>>("a", "b", "c");


Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow