Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using IQueryable<TEntity> instead DbSet<TEntity> problem

i stumbled to the next problem... I have database context:

// 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; } } 
   ...
}

And i try get all hardwares, which doesnt exists in ProviderHardwares table:

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

If i use PrimaryDbContext strictly such as "PrimaryDbContext db = new PrimaryDbContext();" all work fine. But if i use it implicitly "IDbContext db = new PrimaryDbContext();" that i get an exception:

Unable to create a constant value of type 'ConfiguratorMvcApplication.DomainModels.ProviderHardware'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.

Summarize, i can't replace a DbSet on an IQueryable. And how i can use unit testing in this case? I hope someone have resolved this problem yet... Thank in advance very much!

like image 417
xtmq Avatar asked Aug 21 '11 15:08

xtmq


1 Answers

I ended up having two properties for each DbSet: one of type IQueryable, and one of type DbSet. The IQueryable property is defined in the interface, and it relays the calls to the concrete implementation (property of type DbSet), as follows:

// 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; }

Having this setup, I was able to get mocking to work correctly and could unit test the code.

This is definitely too late for the OP, but maybe this helps someone who is struggling with the same question, as I did.

like image 116
Developer Avatar answered Oct 14 '22 13:10

Developer