2010-09-23 14 views
8

Używam Entity Framework 4 w moim projekcie. Ramowa stworzył swój własny ciąg połączenia, więc moja web.config connectionStrings sekcja plik wygląda następujące:Entity Framework - nadmiarowy ciąg połączenia

<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> 

Pierwszy ciąg połączenia nazywane ApplicationServices jest mój oryginalny. Drugi, o nazwie VNKEntities został utworzony podczas generowania modelu.

Po sprawdzeniu wygenerowany * .edmx plik, stwierdziliśmy, że ten model jest odniesienie jej ciąg połączenia, który znajduje się poniżej:

/// <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(); 
    } 

Moje pytanie brzmi jak mogę pozbyć się VNKEntities ciąg połączenia i pozostaw tylko ApplicationServices, do którego będę odwoływać się z mojego modelu? Chciałbym mieć tylko jeden ciąg połączenia z bazą danych, ponieważ używam tylko jednej bazy danych (zastąpienie parametru konstruktora od name=VNKEntities do name=ApplicationServices nie działa).

Pozdrowienia

Odpowiedz

3

Mimo że można utworzyć połączenie w kodzie, jak @gandjustas wskazuje (+1), nie można uciec od posiadania ciąg połączenia lub EntityConnection.

To dlatego, że nie jest w rzeczywistości zbędny. Tak, część połączenia z bazą danych jest zbędna, a @gandjustas pokazuje, jak usunąć tę nadmiarowość. Jednak łańcuch połączenia struktury encji zawiera również informacje o modelu, których nie ma nigdzie w ciągu połączenia, który chcesz zachować. Ta informacja o modelu musi skądś pochodzić. Czy chcesz wyeliminować ciąg połączenia struktury encji i użyć konstruktora listy parametrów na ObjectContext, wyeliminowałbyś wszystkie odniesienia do modelu.

+0

Dzięki za szczegółowe wyjaśnienie, które pomogło mi zrozumieć, dlaczego powinienem wybrać rozwiązanie podane przez @ gandjustas dla rozwiązania mojego problemu. – jwaliszko

1

Miałem ten sam problem. Rozwiązałem go w następujący sposób:

Utworzono dwa pliki edmx, ale podczas tworzenia drugiego pliku edmx zignorowałem ciąg połączenia, który ma zostać zapisany w pliku konfiguracyjnym. W ten sposób mój plik konfiguracyjny będzie zawierał tylko jeden ciąg połączenia. potem modyfikować następujące linie w moim ciąg połączenia:

<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" /> 

Wystarczy zastąpić "res: //model1.csdl" z "res: // * /" i działa jak czar.

Możesz określić nazwę połączenia w konstruktorze klasy dbcontext jak:

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

Uwaga: Używam Entity Framework 5.0.

1

Dostarczę pełną implementację, którą zrobiłem, aby rozwiązać ten problem (na podstawie wskazówek gandjustas). Napisałem prosty otoki dla kontekstu, które mogą być używane w następujący sposób:

using (var wrapper = new ContextWrapper<VNKEntities>()) 
{ 
    // do your stuff based on wrapper.Context 
} 

Rodzaj ContextWrapper to szablon, który po prostu owija kontekst, który jest zbudowany tylko w nieco inny sposób (przy użyciu tylko jednego ciąg połączenia), a następnie odsłonięte według właściwości. Jego wewnętrzna implementacja znajduje się poniżej:

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; 
    } 
} 

Widać użycie niestandardowej klasy o nazwie 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; 
    } 
} 

Więc teraz można mieć ciąg jedno połączenie:

<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> 

i metadanych zdefiniowane w sekcji ustawień aplikacji (drugi klucz wskazuje na montaż, w którym faktycznie przechowywany jest twój model domeny):

<appSettings> 
    <add key="MetadataWorkspacePaths" value="res://*/VNKModel.csdl|res://*/VNKModel.ssdl|res://*/VNKModel.msl" /> 
    <add key="MetadataAssemblyNameToConsider" value="VNK.Models" /> 
</appSettings> 

Logika dla typu Setting jest prosta, ponieważ po prostu wyciąga ustawienia z pliku konfiguracyjnego.

Powiązane problemy