1

We have three components: WinForm-Rich-Client, IIS-Webserver using WebApi, entity framework for most of the database queries.

I was given a code base and i am lost. I unterstand that some classes Student are passed dynamically around using TEntityType. I the msdn docs i read that you can use this approach when you do not statically know the type of T.

I am trying to understand the lines below, what they do and if the relations between all the interfaces and abstract classes have any benefits

var students = DbEntityAccess.Query<Students>().ToList();

// the query member from Our.DAL.Interfaces.IEntityAccess 
IQueryable<TEntTyp> 
              Query<TEntTyp>(Expression<Func<TEntTyp, bool>> query)
                  where TEntTyp: class;

DBEntityAccesss

Definition (F12) and implementation for DBEntityAccesss both lead to

namespace Our.Webservice.Controllers
{
   public abstract class SessionBaseController : ApiController
   {
      protected IEntityAccess DbEntityAccess { get; private set; }
   }
}

Sidenote: Visual Studio suggests to rename DbEntityAccess to GetDbEntityAccess

IEntityAccess

The definition (F12) and the implementation (STRG+F12) of IEntityAccess are these

// Definition of SessionBaseController.IEntityAccess
namespace Our.DAL.Interfaces
{
  public interface IEntityAccess
  {
    IQueryable<TEntTyp> 
       Query<TEntTyp>(Expression<Func<TEntTyp, bool>> query)
            where TEntTyp: class;
  }
}


// Implementation of SessionBaseController.IEntityAccess
namespace Our.DAL.Implementations
{
   public class TpdEntities : DbAccess, IEntityAccess
   {
     // TEntityType shortened to TEntTyp 
     public IQueryable<TEntTyp> Query<TEntTyp>() where TEntTyp: class
     {
       return Set<TEntTyp>();
     }
   }
}

Our.DAL.Implementations.TpdEntities

The class Our.DAL.Implementations.TpdEntities is implementing the interface Our.DAL.Interfaces.IEntityAccess (see above) and inherits from DbAccess which is an abstract class that inherits from System.Data.Entity.DbContext

Our.DAL.Implementations.DbAccess

It is unclear what DbAccess contributes.

namespace Our.DAL.Implementations
{
  public abstract class DbAccess : DbContext
  {
      // Constructor
      protected DbAccess()
          : base("name=TPDEntities")
      {
          Configuration.AutoDetectChangesEnabled = false;
      }
  }
}

Questions

How is the first part wired up

  • What does query do, how and when does EF come into play var students = DbEntityAccess.Query<Students>().ToList();

  • What does the part Query<TEntTyp>(Expression<Func<TEntTyp, bool>> query) where TEntTyp: class; do?

  • To me it is unclear what Query does?
  • How does it query the passed T TEntTyp?
  • What does Expression<Func<TEntTyp, bool>> query?

Thanks and regards

surfmuggle
  • 5,527
  • 7
  • 48
  • 77
  • do you really need understand all of them to maintain the project? – Lei Yang Jun 01 '17 at 02:59
  • Yes i would like to understand what the code does. We are facing performance troubles. in our db trace we found certain db-queries that are very slow - the select all columns without any conditions (predicates). – surfmuggle Jun 01 '17 at 07:21

1 Answers1

1

So the Implementation of IEntityAccess should not work because it is missing the parameter Expression<Func<TEntTyp, bool>> query it should look like:

namespace Our.DAL.Implementations
{
   public class TpdEntities : DbAccess, IEntityAccess
   {
     // TEntityType shortened to TEntTyp 
     public IQueryable<TEntTyp> Query<TEntTyp>(Expression<Func<TEntTyp, bool>> query) 
     where TEntTyp: class
     {
       return Set<TEntTyp>().Where(query);
     }
   }
}

As it is written now, there is no difference than directly accessing the DbAccess class. If you look at DbAccess it inherits DbContext(Entity Framework) and holds the collections.

What does query do, how and when does EF come into play var students = DbEntityAccess.Query().ToList();

So, DbEntityAccess is an interface, but has an implementation of TpdEntities. Assuming that is what is set, is the same as DbAccess.Students.

What does the part Query<TEntTyp>(Expression<Func<TEntTyp, bool>> query) where TEntTyp: class; do?

This is the interesting part. You can use a Predicate to filter the collection further. For example, you need only currently registered students. If you try this with DbAccess it would look like:

var registeredStudents = DbAccess.Students.Where(student => student.IsRegistered);

The Query method does the same thing:

var registeredStudents = DbEntityAccess.Query(student => student.IsRegistered);    

The student => student.IsRegistered is a predicate Func<Student, bool> that returns a student if they satisfy some condition.

Why would you want all this abstraction?

For future extensibility. Let's imagine that this controller is only concerned about currently registered students and will never need past students. the TpdEntities could then be switched for

namespace Our.DAL.Implementations
{
   public class CurrentStudentsRepository : DbAccess, IEntityAccess
   {
     // TEntityType shortened to TEntTyp 
     public IQueryable<Student> Query<Student>(Expression<Func<Student, bool>> query) 
     where Student: class
     {
       return Set<Student>().Where(student => student.IsRegistered).Where(query);
     }
   }
}

Because this returns IQueryable you can then further filter the collection before asking the Database to get the data.

var students = DbEntityAccess.Query(student => student.FirstName == "Jim");

will return all currently enrolled students with a first name of Jim in a very readable way.

robjam
  • 969
  • 1
  • 11
  • 24