In this tutorial we will create a fake DbContext instance.

Effort does not support the creation of DbContext directly, altering the behavior of a DbContext class requires the creation of fake DbConnection object. So the DbContext class should have the appropriate constructor:

public class MyDbContext : DbContext
{
    public MyDbContext(DbConnection connection) 
        : base(connection, true)
    {
    }
}

 

The DbConnectionFactory class provides helper methods to create fake DbConnection objects that can be used as the argument for the previously mentioned constructor.

DbConnection connection = Effort.DbConnectionFactory.CreateTransient();

MyDbContext context = new MyDbContext(connection);

 

Of course, the initial data can be set by using an appropriately created data loader.

IDataLoader loader = new Effort.DataLoaders.CsvDataLoader(csvFiles);

DbConnection connection = Effort.DbConnectionFactory.CreateTransient(loader);

MyDbContext context = new MyDbContext(connection);

 

Since the release of Visual Studio 2012 all kind of Entity Framework templates use DbContext by default, even if you want to use the Database First or Model First approach. In these cases if you used the previous technique, you would get an UnintentionalCodeFirstException.

If you experienced this issue you should use Effort in another way. Instead of DbConnectionFactory use the EntityConnectionFactory component and pass a connection string that refers to the EDMX file, just like if you used an ObjectContext.

EntityConnection connection =
    Effort.EntityConnectionFactory.CreateTransient("name=connectionString");

MyDbContext context = new MyDbContext(connection);

Last edited May 27, 2014 at 9:02 AM by tamasflamich, version 22

Comments

bizarrodavid May 10, 2016 at 8:22 PM 
@jdege: Copy/paste the connection string that is in your App.config file. Paste this into the argument for CreateTransient() in the code above. This should be the connection string that starts with "metadata=res://*/BlahBlah.csdl|..." You will also need to turn the " tokens into actual single quotes.

After I did this I was able to get the sample to work using EF6, "Effort.EF6" library from nuget (as distinct from "Effort" without the EF6) and using a Database First approach.

Togakangaroo May 14, 2015 at 2:17 AM 
So I'm not sure what's going on here...what populates the entity framework `IDbSet` that you need?

PsMaster Mar 30, 2015 at 11:43 AM 
jdege, just use the name from config file. Or if you generated code from database, check the generated DbContext file, it should have a constructor:
public MyDBEntities()
: base("name=MyDBEntities")
{
}

Use the "name=MyDBEntities" string.

LeEmo86 Jun 17, 2014 at 3:23 PM 
I had the UnintentionalCodeFirstException as described above and tried to use the EntityConnectionFactory workaround, again as described above. However I'm having a "System.ArgumentException : String cannot have zero length." on the creation of the EntityConnection.

The connection string is defined in the app.config for the test runner and works with non-Effort based tests some of which read / write to the test database. I have removed any sensitive data:
<add name="MyConnectionString" connectionString="metadata=res://*/;provider=System.Data.SqlClient;provider connection string='data source=localhost;initial catalog=MyDatabaseName;persist security info=True;user id=myuser;password=mypassword;MultipleActiveResultSets=True;App=EntityFramework'" providerName="System.Data.EntityClient" />

The stack trace for the error is below:
System.ArgumentException : String cannot have zero length.
at System.Reflection.RuntimeAssembly.GetResource(RuntimeAssembly assembly, String resourceName, ref UInt64 length, StackCrawlMarkHandle stackMark, Boolean skipSecurityCheck)
at System.Reflection.RuntimeAssembly.GetManifestResourceStream(String name, ref StackCrawlMark stackMark, Boolean skipSecurityCheck)
at System.Reflection.RuntimeAssembly.GetManifestResourceStream(String name)
at Effort.Internal.Common.MetadataWorkspaceHelper.ParseResources(String resPath, List`1 csdl, List`1 ssdl, List`1 msl)
at Effort.Internal.Common.MetadataWorkspaceHelper.ParseMetadata(String metadata, List`1 csdl, List`1 ssdl, List`1 msl)
at Effort.Internal.Common.MetadataWorkspaceHelper.Rewrite(String metadata, String providerInvariantName, String providerManifestToken)
at Effort.EntityConnectionFactory.<GetEffortCompatibleMetadataWorkspace>b__1(String metadata)
at Effort.Internal.Caching.MetadataWorkspaceStore.<>c__DisplayClass1.<GetMetadataWorkspace>b__0()
at System.Lazy`1.CreateValue()
at System.Lazy`1.LazyInitValue()
at System.Lazy`1.get_Value()
at Effort.Internal.Caching.ConcurrentCache`2.Get(TKey key, Func`1 factory)
at Effort.Internal.Caching.MetadataWorkspaceStore.GetMetadataWorkspace(String metadata, Func`2 workspaceFactoryMethod)
at Effort.EntityConnectionFactory.GetEffortCompatibleMetadataWorkspace(ref String entityConnectionString)
at Effort.EntityConnectionFactory.CreateTransient(String entityConnectionString, IDataLoader dataLoader)
at Effort.EntityConnectionFactory.CreateTransient(String entityConnectionString)
at NUnitTests.EffortTests.BasicAdd() in EffortTests.cs: line 43

Can anyone tell me what I'm doing wrong?

Thanks in advance,

Liam

jBelanger Jun 11, 2014 at 3:48 PM 
In my case, it was easier to just create a new ProviderFactory that EntityFramework will use to get new connections. This way your DbContext class don't require to have a constructor with a DbConnection parameter.

In your composition root (global.asax)

Database.DefaultConnectionFactory = new OfflineProviderFactory();

public class OfflineProviderFactory : IDbConnectionFactory
{
public DbConnection CreateConnection(string nameOrConnectionString)
{
return Effort.DbConnectionFactory.CreateTransient();
}
}

tamasflamich Dec 28, 2013 at 1:18 AM 
You can learn about entity connection string here:
http://msdn.microsoft.com/en-us/library/cc716756%28v=vs.110%29.aspx

jdege Dec 27, 2013 at 10:06 PM 
What, exactly, does a "connection string that refers to the EDMX file" look like?