This is more a solution / work around than a real question. I post it here since I could not find this solution when the stack overflowed or even after a lot of Google.
Problem:
I have an MVC 3 webapp using EF 4 code that I want to write for unit tests. I also use NCrunch to run unit tests on the go, as I code, so I would like to avoid support in a real database here.
Other solutions:
IDataContext
I found this to be the most acceptable way to create a datacontext in memory. This effectively involves writing the IMyDataContext interface for your MyDataContext, and then using the interface in all of your controllers. An example of this is here .
This is the route I went from the very beginning, and even got to writing a T4 template to extract IMyDataContext from MyDataContext, since I don't like to support duplicate dependent code.
However, I quickly found that some Linq statements do not work when using IMyDataContext instead of MyDataContext. In particular, such requests raise a NotSupportedException
var siteList = from iSite in MyDataContext.Sites
let iMaxPageImpression = (from iPage in MyDataContext.Pages where iSite.SiteId == iPage.SiteId select iPage.AvgMonthlyImpressions).Max()
select new { Site = iSite, MaxImpressions = iMaxPageImpression };
My decision
It was pretty simple. I just subclassed MyInMemoryDataContext for MyDataContext and overrided all the IDbSet <..> properties, as shown below:
public class InMemoryDataContext : MyDataContext, IObjectContextAdapter
{
public bool SaveChangesWasCalled { get; private set; }
public InMemoryDataContext()
{
InitializeDataContextProperties();
SaveChangesWasCalled = false;
}
private void InitializeDataContextProperties()
{
Type myType = GetType().BaseType;
var DbSets = myType.GetProperties().Where(x => x.PropertyType.IsGenericType && x.PropertyType.GetGenericTypeDefinition() == typeof(IDbSet<>)).ToList();
foreach (var iDbSetProperty in DbSets)
{
var concreteCollectionType = typeof(CollectionDbSet<>).MakeGenericType(iDbSetProperty.PropertyType.GetGenericArguments());
var collectionInstance = Activator.CreateInstance(concreteCollectionType);
iDbSetProperty.SetValue(this, collectionInstance,null);
}
}
ObjectContext IObjectContextAdapter.ObjectContext
{
get { return null; }
}
public override int SaveChanges()
{
SaveChangesWasCalled = true;
return -1;
}
}
CollectionDbSet < > FakeDbSet < > ( IDbSet ObservableCollection ObservableCollection.AsQueryable()).
, NCrunch, " ".
-, , LINQ MyDataContext. , , Linq-To-Entity, Linq-To-Objects ( ).
, Ninject InMemoryDataContext MyDataContext . Ninject MyDataContext ( app.config).
if(Global.RunIntegrationTest)
DependencyInjector.Bind<MyDataContext>().To<MyDataContext>().InSingletonScope();
else
DependencyInjector.Bind<MyDataContext>().To<InMemoryDataContext>().InSingletonScope();
, - , .