Entity Framework - избыточная строка подключения

Я использую Entity Framework 4 в своем проекте. Framework создал свою собственную строку подключения, поэтому мой web.config Файл раздела connectionStrings выглядит следующим образом:

  <connectionStrings>
    <add name="ApplicationServices" connectionString="data source=localhost;user id=user;pwd=pass;initial catalog=VNK" providerName="System.Data.SqlClient" />    
    <add name="VNKEntities" connectionString="metadata=res://*/VNKModel.csdl|res://*/VNKModel.ssdl|res://*/VNKModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=localhost;Initial Catalog=VNK;User ID=user;Password=pass;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>

Первая строка подключения называется ApplicationServices мой оригинальный. Второй называется VNKEntities был создан при создании модели.

Когда я проверил сгенерированный файл *.edmx, я обнаружил, что эта модель ссылается на строку подключения, как показано ниже:

    /// <summary>
    /// Initializes a new VNKEntities object using the connection string found in the 'VNKEntities' section of the application configuration file.
    /// </summary>
    public VNKEntities() : base("name=VNKEntities", "VNKEntities")
    {
        this.ContextOptions.LazyLoadingEnabled = true;
        OnContextCreated();
    }

Мой вопрос, как я могу избавиться от VNKEntities Строка подключения, и оставить только ApplicationServicesна что я буду ссылаться из моей модели? Я хотел бы иметь только одну строку подключения к базе данных, потому что я использую только одну базу данных (заменяя параметр конструктора из name=VNKEntities в name=ApplicationServices не работает).

С уважением

4 ответа

Решение
  1. Вручную создать DbConnection из обычной строки подключения
  2. Ручное создание объекта MetadataWorkspace.
  3. Создайте EntityConnection, используя этот ctor.
  4. Передайте соединение сущности конструктору ObjectContext.

Хотя вы можете создать соединение в коде, как указывает @gandjustas (+1), вы не можете избежать наличия строки соединения или EntityConnection,

Это потому, что это на самом деле не избыточно. Да, часть соединения с базой данных является избыточной, и @gandjustas показал вам, как удалить эту избыточность. Тем не менее, строка соединения сущности также содержит информацию о вашей модели, которую нет нигде в строке соединения, которую вы хотите сохранить. Эта модель информации должна откуда-то прийти. Если бы вы удалили строку подключения структуры сущностей и использовали конструктор списка параметров в ObjectContextВы бы устранили все ссылки на модель.

Я предоставлю полную реализацию, которую я сделал, чтобы решить эту проблему (на основе подсказок 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 это просто, так как он просто вытаскивает настройки из файла конфигурации.

У меня такая же проблема. Я решил это следующим образом:

Я создал два файла EDMX, но при создании второго файла EDMX, я проигнорировал строку подключения для сохранения в файле конфигурации. Таким образом, мой файл конфигурации будет содержать только одну строку подключения. Затем я изменил следующие строки в строке подключения:

<add name="MyDbContext" connectionString="metadata=res://*/;provider=System.Data.SqlClient;provider connection string=&quot;data source=abc;initial catalog=mydb;persist security info=True;user id=myuser;password=password;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />

Просто замените "res://model1.csdl" на "res://*/", и это работает как шарм.

Вы можете указать это имя соединения в конструкторе вашего класса dbcontext, например:

public MyDbContext() : base("name=NameOfYourConnectionString") //  Name of your connection string
{ }

Примечание. Я использую Entity Framework 5.0.

Другие вопросы по тегам