protected override void InitializeContext()
{
CheckContextNotDisposed();
if (_objectContext == null)
{
if (_creatingModel)
{
throw Error.DbContext_ContextUsedInModelCreating();
}
try
{
var contextInfo = DbContextInfo.CurrentInfo;
if (contextInfo != null)
{
ApplyContextInfo(contextInfo);
}
_creatingModel = true;
if (_createdWithExistingModel)
{
// A DbCompiledModel was supplied, which means we should just create the ObjectContext from the model.
// The connection cannot be an EF connection because it would then contain a second source of model info.
if (_internalConnection.ConnectionHasModel)
{
throw Error.DbContext_ConnectionHasModel();
}
Debug.Assert(_model != null);
_objectContext = _model.CreateObjectContext<ObjectContext>(_internalConnection.Connection);
}
else
{
// No model was supplied, so we should either create one using Code First, or if an EF connection
// was supplied then we should use the metadata in that connection to create a model.
if (_internalConnection.ConnectionHasModel)
{
_objectContext = _internalConnection.CreateObjectContextFromConnectionModel();
}
else
{
// The idea here is that for a given derived context type and provider we will only ever create one DbCompiledModel.
// The delegate given to GetOrAdd may be executed more than once even though ultimately only one of the
// values will make it in the dictionary. The RetryLazy ensures that that delegate only gets called
// exactly one time, thereby ensuring that OnModelCreating will only ever be called once. BUT, sometimes
// the delegate will fail (and throw and exception). This may be due to some resource issue--most notably
// a problem with the database connection. In such a situation it makes sense to have the model creation
// try again later when the resource issue has potentially been resolved. To enable this RetryLazy will
// try again next time GetValue called. We have to pass the context to GetValue so that the next time it tries
// again it will use the new connection.
var key = _cacheKeyFactory(Owner);
var model
= _cachedModels.GetOrAdd(
key, t => new RetryLazy<LazyInternalContext, DbCompiledModel>(CreateModel)).GetValue(this);
_objectContext = model.CreateObjectContext<ObjectContext>(_internalConnection.Connection);
// Don't actually set the _model unless we succeed in creating the object context.
_model = model;
}
}
_objectContext.ContextOptions.EnsureTransactionsForFunctionsAndCommands = _initialEnsureTransactionsForFunctionsAndCommands;
_objectContext.ContextOptions.LazyLoadingEnabled = _initialLazyLoadingFlag;
_objectContext.ContextOptions.ProxyCreationEnabled = _initialProxyCreationFlag;
_objectContext.ContextOptions.UseCSharpNullComparisonBehavior = !_useDatabaseNullSemanticsFlag;
_objectContext.CommandTimeout = _commandTimeout;
_objectContext.ContextOptions.UseConsistentNullReferenceBehavior = true;
_objectContext.InterceptionContext = _objectContext.InterceptionContext.WithDbContext(Owner);
ResetDbSets();
_objectContext.InitializeMappingViewCacheFactory(Owner);
}
finally
{
_creatingModel = false;
}
}
}