DbContext, EF и LINQ - Каков наилучший способ предоставления методов в DbContext через интерфейс? - PullRequest
3 голосов
/ 19 марта 2012

Я довольно новичок в EF и DBContext, и поэтому ищу несколько советов о том, как лучше изложить мой код для службы WCF с использованием EF, Stored Procs или SQL.

Фон

У меня есть внешний интерфейс MVC3, который подключен к сервисному уровню WCF для доступа к данным (Oracle). Фактический доступ к данным осуществляется через отдельную библиотеку классов DAO.

Моя цель состоит в том, чтобы уровень обслуживания использовал только интерфейс, на котором он может вызывать набор методов для возврата данных. Я не хочу, чтобы сервисный уровень знал, что мы используем EF для запросов, поскольку я могу при необходимости заменить медленные биты EF на Stored Procs или обычный текст SQL.

Где я сейчас нахожусь

У меня есть интерфейс для моей базы данных IDB и конкретная реализация IDB, MyDB, которая также реализует DBContext. MyDb имеет пару производных классов, называемых MyStdDB и MySecureDB. Когда мне нужен интерфейс, я вызываю мой фабричный метод, который работает, если мне нужен стандартный или безопасный db, а затем возвращает его в мою переменную интерфейса.

Код WCF:

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

DBФабричный код:

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

Поэтому, когда я хочу запросить запрос, я хочу задать _db.GetAccount () в рамках моего вызова службы. На данный момент я добавил это как метод расширения интерфейса IDB. Причина этого состояла в том, чтобы служба не видела мои сущности EF, и это позволяет разбивать запросы на логические файлы, например. Класс, полный запросов CUSTOMER, класс, полный запросов ACCOUNT.

Код IDB:

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

Код MyDB:

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

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

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

Метод расширения:

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

Выпуск

Как видите, мне нужно привести интерфейс в конкретный объект, чтобы я мог добраться до сущностей EF. Это потому, что сущности находятся на реализации класса, а не интерфейса. Метод Extension находится в моей библиотеке классов DAO, поэтому он изменился бы, когда изменилась моя реализация IDB, но мне все равно это не нравится. Есть ли лучший способ сделать это? Я смотрю на DI?

Большие драйверы для меня:

  • Доступ к базе данных должен осуществляться только через интерфейс, так как мы можем заменить БД в ближайшее время.
  • Методы доступа к данным должны быть скрыты от службы. Я должен иметь доступ к данным только через методы, предоставляемые интерфейсом / методами расширения и т. Д.

1 Ответ

2 голосов
/ 19 марта 2012

Временное решение - переместить ваш GetAccount в IDB вместо использования методов расширения:

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

Это решит вашу проблему, потому что MyDB будет реализовывать метод, а все производные классы будут использовать реализацию какЧто ж.Если они предоставляют другую реализацию, они просто переопределят ее.

Методы доступа к данным должны быть скрыты от службы.Я должен иметь возможность получать доступ к данным только через методы, предоставляемые интерфейсом / методами расширения и т. Д.

Но это не так.Метод / свойство скрыто, если оно не является общедоступным, но в настоящее время любая ваша служба может преобразовать IDB в MyDB и получить прямой доступ к DbSet.

...