DbContext, EF and LINQ - What's the best way to expose methods in a DbContext through an interface?

I am new to EF and DBContext, so I would like to provide some advice on how to best outline my code for a WCF service using EF, Stored Procs, or SQL.

Background

I have an MVC3 frontend connected to the WCF service layer for data access (Oracle). The actual data access is through a separate DAO class library.

My goal is for the service layer to only use an interface on which it can call a set of methods to return data. I don't want the service layer to be aware that we are using EF for queries, as I can replace the slow EF bits with Stored Procs or plain SQL if needed.

Where am I

I have an interface for my database's IDB and an explicit IDB implementation, MyDB, which also implements DBContext. MyDb has several derived classes MyStdDB and MySecureDB. When I need an interface, I call my factory method, which works if I need a standard or safe db, and then returns it to my interface variable.

WCF code:

public List<string> GetAccount() {
   IDB _db = DBFactory.GetInstance();
   return _db.GetAccount();
}

      

DBFactory code:

 pubilc class DBFactory {
   pubilc static IDB GetInstance()
   {
     if bSecure
        return MySecureDB;
     else 
        return MyStdDB;
   }
 }

      

So when I want to make a request, I want to ask _db.GetAccount () in my service call. At the moment I have added this as an extension method on the IDB interface. The reason for this was to prevent the service from seeing my EF objects and it allows qqueries to be copied to logical files for example. A class filled with CUSTOMER requests, a class full of ACCOUNT requests.

IDB code:

public interface IDB : IDisposable
{
    ObjectContext UnderlyingContext { get; }
    int SaveChanges();
}

      

MyDB code:

public class MyDB : DbContext, IDB 
{
    ObjectContext IDB.UnderlyingContext
    {
        get
        {
            return ((IObjectContextAdapter)this).ObjectContext;
        }
    }

    int IDB.SaveChanges()
    {
        return SaveChanges();
    }       

    public DbSet<Customer> Customer { get; set; }
}

      

Extension method:

public static List<string> GetAccount(this IDB _db)
{
    ((MyDB)_db).Customer.AsNoTracking().First();
}

      

Problem

As you can see, I have to pass the interface to a specific object so that I can get the EF objects. This is because the entities are on the implementation of the class, not on the interface. The extension method is in my DAO class library, so this will change when my implementation with IDB changes, but I still don't like it. Is there a better way to do this? Am I looking at DI?

Big drivers for me:

  • The database should only be accessed through the interface, as we may soon be replacing db.
  • Data access methods must be hidden from the service. I should only be able to access data using methods provided by interface / extension methods, etc.
+3


source to share


1 answer


A workaround is moving yours GetAccount

to IDB

instead of using extension methods:

public interface IDB : IDisposable
{
    ObjectContext UnderlyingContext { get; }
    List<string> GetAccount();
    int SaveChanges();
}

      

It solves your problem because it MyDB

will implement the method and all derived classes will use the implementation as well. If they provide a different implementation, they simply override it.



Data access methods must be hidden from the service. I had to be able to access the data through methods provided by interface / extension methods, etc.

But this is not the case. The method / property is hidden if it is not public, but currently any of your services can convert IDB

to MyDB

and access directly DbSet

.

+2


source







All Articles