Я предоставлю полную реализацию, которую я сделал, чтобы решить эту проблему (на основе подсказок gandjustas). Я написал простую оболочку для контекста, которую можно использовать следующим образом:
using (var wrapper = new ContextWrapper<VNKEntities>())
{
// do your stuff based on wrapper.Context
}
Тип ContextWrapper
- это шаблон, который просто оборачивает контекст, который просто создается немного другим способом (используя только одну строку подключения), а затем предоставляется свойством. Его внутренняя реализация размещена ниже:
public class ContextWrapper<TContext> : IDisposable
where TContext : ObjectContext
{
private TContext _context;
private EntityConnectionManager _manager;
private bool _disposed;
public ContextWrapper()
: this(true)
{
}
public ContextWrapper(bool lazyLoadingEnabled)
{
_disposed = false;
_manager = new EntityConnectionManager();
_context = (TContext)Activator.CreateInstance(typeof(TContext), _manager.Connection);
_context.ContextOptions.LazyLoadingEnabled = lazyLoadingEnabled;
}
~ContextWrapper()
{
Dispose(false);
}
public TContext Context
{
get { return _context; }
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
if (_manager != null)
{
_manager.Dispose();
_manager = null;
}
var ctx = _context as IDisposable;
if (ctx != null)
{
ctx.Dispose();
_context = null;
}
}
}
_disposed = true;
}
}
Вы можете увидеть использование пользовательского класса с именем EntityConnectionManager
:
internal class EntityConnectionManager : IDisposable
{
private DbConnection _connection;
private EntityConnection _entityConnection;
private volatile bool _disposed;
public EntityConnectionManager()
{
var workspace = new MetadataWorkspace(Setting.MetadataWorkspacePaths.Split('|'), new[] { Assembly.ReflectionOnlyLoad(Setting.MetadataAssemblyNameToConsider) });
_connection = new SqlConnection(Setting.ConnectionString);
_entityConnection = new EntityConnection(workspace, _connection);
_disposed = false;
}
public EntityConnection Connection
{
get { return _entityConnection; }
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
if (_connection != null)
{
_connection.Dispose();
_connection = null;
}
if (_entityConnection != null)
{
_entityConnection.Dispose();
_entityConnection = null;
}
}
}
_disposed = true;
}
}
Так что теперь вы можете иметь одну строку подключения:
<connectionStrings>
<add name="ApplicationServices" connectionString="data source=localhost;user id=user;pwd=pass;initial catalog=VNK;Pooling=False;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
</connectionStrings>
и метаданные, определенные в разделе настроек приложения (второй ключ указывает на сборку, где фактически хранится ваша модель домена):
<appSettings>
<add key="MetadataWorkspacePaths" value="res://*/VNKModel.csdl|res://*/VNKModel.ssdl|res://*/VNKModel.msl" />
<add key="MetadataAssemblyNameToConsider" value="VNK.Models" />
</appSettings>
Логика для типа Setting
проста, поскольку она просто извлекает настройки из файла конфигурации.