Использование IQueryable <TEntity>вместо DbSet <TEntity>проблема - PullRequest
6 голосов
/ 21 августа 2011

я наткнулся на следующую проблему ... У меня есть контекст базы данных:

// For support unit testing... 
public interface IDbContext : IDisposable
{
   IQueryable<Hardware> Hardwares { get; }
   IQueryable<ProviderHardware> ProviderHardwares { get; }
}

// Real DbContext (EF 4.0, Code First)
public class PrimaryDbContext : DbContext, IDbContext
{
   public DbSet<Hardware> Hardwares { get; set; }
   public DbSet<ProviderHardware> ProviderHardwares { get; set; }

   IQueryable<Hardware> IDbContext.Hardwares
     { get { return Hardwares; } }
   IQueryable<ProviderHardware> IDbContext.ProviderHardwares
     { get { return ProviderHardwares; } } 
   ...
}

И я пытаюсь получить все аппаратные средства, которых нет в таблице ProviderHardwares:

var hardwaresRemoved = db.Hardwares.Where(i => (i.IsAvailable == true) &&
   (db.ProviderHardwares.Count(j => j.Article == i.Article) == 0)).ToList();

Если я использую PrimaryDbContext строго, например, "PrimaryDbContext db = new PrimaryDbContext ();" все работает нормально. Но если я использую это неявно "IDbContext db = new PrimaryDbContext ();" что я получаю исключение:

Невозможно создать постоянное значение типа 'ConfiguratorMvcApplication.DomainModels.ProviderHardware. Только примитивные типы (такие как Int32, String и Guid) поддерживаются в этот контекст.

Подводя итог, я не могу заменить DbSet на IQueryable. И как я могу использовать модульное тестирование в этом случае? Я надеюсь, что кто-то решил эту проблему еще ... Заранее большое спасибо!

Ответы [ 2 ]

1 голос
/ 14 июня 2016

В итоге у меня было два свойства для каждого DbSet: одно типа IQueryable и одно типа DbSet.Свойство IQueryable определено в интерфейсе, и оно передает вызовы конкретной реализации (свойство типа DbSet) следующим образом:

// Exists in the interface
public IQueryable<AccountContact> AccountContacts
{ 
    get
    {
        return DbAccountContacts;
    }
    set
    {
        DbAccountContacts = (DbSet<AccountContact>)value; 
    }
}

// Exists only in the implementation
public DbSet<AccountContact> DbAccountContacts { get; set; }

Имея эту настройку, я смог заставить mocking работать правильнои может тестировать код модулем.

Это определенно слишком поздно для ОП, но, возможно, это поможет тому, кто борется с тем же вопросом, что и я.

0 голосов
/ 01 сентября 2011

Я предлагаю вам лучше сохранить DbSets и выполнить ИНТЕГРАЦИОННОЕ ТЕСТИРОВАНИЕ , включая базу данных.

Потому что, хотя прохождение модульного теста с макетом БД может быть несколько полезно, вам будет лучше тестировать с реальной базой данных (но это не модульное тестирование).

На ClassInitialize сотрите базу данных и / или создайте исходные данные для тестирования.

Если вы создаете файл App.config со строкой соединения, у вас может быть отдельная тестовая база данных, и если вы используете EF Code First, вы получаете его бесплатно.

С уважением.

...