Using IQueryable<TEntity> instead DbSet<TEntity> problem

 ̄綄美尐妖づ 提交于 2019-12-07 02:22:38

问题


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!


回答1:


I suggest you better keep DbSets and do INTEGRATION TESTING including the database.

Because, although passing a unit test with a mock of a DB could be somewhat usefull, you are going to be better off testing with real database (but it's not unit testing).

On the ClassInitialize erase the database and/or create the initial data for testing.

If you create an App.config file with a connection string you can have a separate test database, and if you are using EF Code First, you get it for free.

Best regards.




回答2:


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.



来源:https://stackoverflow.com/questions/7139352/using-iqueryabletentity-instead-dbsettentity-problem

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!