2013-02-23 11 views
8

Przy użyciu WPF i ramy encji Mam app.config, który wygląda tak:% APPDATA% w ciąg połączenia nie jest zastąpiony rzeczywistego folderu?

<?xml version="1.0" encoding="utf-8"?> 
<configuration> 
    <connectionStrings> 
    <add name="DatabaseEntities" connectionString="metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlServerCe.4.0;provider connection string=&quot;Data Source=%APPDATA%\Folder\Database.sdf&quot;" providerName="System.Data.EntityClient" /> 
    </connectionStrings> 
</configuration> 

Używając tego kodu to zawsze rzuca się następujący błąd:

System.Data.EntityException: The underlying provider failed on Open. ---> System.Data.SqlServerCe.SqlCeException: The path is not valid. Check the directory for the database. [ Path = %APPDATA%\Folder\Database.sdf ] 

gdy uruchomię ścieżka "% APPDATA% \ Folder \ Database.sdf" z wiersza poleceń działa poprawnie, a jeśli usunę "% APPDATA% i hardcode ścieżka działa dobrze - tak wygląda po prostu jak% APPDATA% po prostu nie jest podstawiana dla rzeczywistego folderu ...

Dziękujemy,

+1

Użyj '| DataDirectory' w łańcuchu połączenia zamiast'% APPDATA% 'Daj mi znać, czy to rozwiąże twój problem. –

Odpowiedz

21

Jak już zostało to zmienione, %APPDATA% lub inne zmienne środowiskowe nie są zastępowane ich odpowiednimi wartościami w łańcuchach połączeń. Warial varialbes są czymś związanym z powłoką systemu operacyjnego. Działają w wierszu polecenia, ponieważ wiersz poleceń jawnie analizuje wprowadzone wartości i zastępuje zmienne środowiskowe. To nie jest coś, co zwykle wykonuje .NET Framwork.

Aby to osiągnąć, należy ręcznie podać wartość dla %APPDATA% (używając Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) lub Environment.GetEnvironmentVariable("APPDATA")). Istnieją dwie opcje:

  1. zmienić ciąg połączenia i wykorzystania |DataDirectory|: (. Zauważ użycie |DataDirectory| w ścieżce do pliku bazy danych)

    <connectionStrings> 
        <add name="DatabaseEntities" connectionString="metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlServerCe.4.0;provider connection string=&quot;Data Source=|DataDirectory|\Database.sdf&quot;" providerName="System.Data.EntityClient" /> 
    </connectionStrings> 
    

    Następnie podać wartość dla |DataDirectory| w głównej aplikacji:

    AppDomain.CurrentDomain.SetData("DataDirectory", 
        Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)); 
    

    Patrz this MSDN page for more information.

  2. Ręcznie wprowadź ciąg połączenia dla klasy ObjectContext. W ten sposób można przeanalizować i zmienić ciąg połączenia:

    public static string GetConnectionString() 
    { 
        var conStr = System.Configuration.ConfigurationManager.ConnectionStrings["DatabaseEntities"].ConnectionString; 
        return conStr.Replace("%APPDATA%", 
         Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)); 
    } 
    

    a później:

    var db = new DatabaseEntities(GetConnectionString()); 
    

    lub podklasy ty ObjectContext klasy i zawsze używać nowego ciąg połączenia:

    public class MyDatabaseEntities : DatabaseEntities 
    { 
        public MyDatabaseEntities() 
         : base(GetConnectionString()) 
        { 
        } 
    
        public static string GetConnectionString() 
        { 
         var conStr = System.Configuration.ConfigurationManager.ConnectionStrings["DatabaseEntities"].ConnectionString; 
         return conStr.Replace("%APPDATA%", 
          Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)); 
        } 
    } 
    

    i używać nowa klasa w dowolnym miejscu.

+0

To jest mój pierwszy raz używając framework entity i szczerze mówiąc nie mogę znaleźć żadnego CODE, w którym jest odczytany ConnectionString, a więc nie ma gdzie dla mnie zrobić .Replace dla APPDATA. Na początku używam programu ConfigurationManager, aby go odczytać, a następnie przeanalizować jego zapisanie, ale widząc, że plik znajduje się w folderze \ Programs Files \, nie mam prawa go zmieniać ...? – JSchwartz

+0

@JSchwartz Dodałem wszystkie wymagane informacje. –

+0

Witam Używam Visual Studio 2013 i nazwa typu lub przestrzeni nazw "ConfigurationManager" nie istnieje w przestrzeni nazw "System.Configuration" (czy brakuje odniesienia do zestawu?) – Cyberguille

1

Trzeba wymienić %APPDATA% w kodzie ze ścieżką względną -

var connectionString = ConfigurationManager.ConnectionStrings["DatabaseEntities"] 
                  .ConnectionString;  
connectionString.Replace("%APPDATA%", 
    Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); 
4

mam inną opcję. Nie musimy niczego wymieniać. Używam poniższego ciągu połączenia bez żadnej zamiany i działa dobrze.

<connectionStrings> 
    <add name="ProjectManagementDBEntities" connectionString="metadata=res://*/Models.ProjectManagementModels.csdl|res://*/Models.ProjectManagementModels.ssdl|res://*/Models.ProjectManagementModels.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=(LocalDB)\MSSQLLocalDB;attachdbfilename=|DataDirectory|\ProjectManagementDB.mdf;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient"/> 
    </connectionStrings> 

Główna zmiana polega data source=(LocalDB)\MSSQLLocalDB;attachdbfilename=|DataDirectory|\ProjectManagementDB.mdf;integrated security=True;

Mam nadzieję, że uratuje komuś.

Powiązane problemy