Entity Framework - избыточная строка подключения - PullRequest
9 голосов
/ 23 сентября 2010

Я использую 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 ]

4 голосов
/ 23 сентября 2010

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

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

3 голосов
/ 23 сентября 2010
  1. Создание DbConnection вручную из обычной строки подключения
  2. Создание вручную MetadataWorkspace объект.
  3. Создание EntityConnection с использованием этого ctor.
  4. Передача соединения сущности конструктору ObjectContext.
1 голос
/ 20 февраля 2013

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

1 голос
/ 19 февраля 2013

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

Я создал два файла 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.

...