none
Globale Variable benötigt RRS feed

  • Frage

  • Hi guys,

    stehe irgendwie uff'm Schlauch.

    Ganz allgemein gefragt: Wie deklariere ich eine Stringvariable, damit diese in allen Formularen meines Projektes zur Verfügung steht. Baue nämlich in mindestens 2 Formularen eine ACCESSverbindung auf und benötige die zuvor von einem Benutzer in einem Objekt der Klasse OpenFileDialog hinterlegten Datenbankdaten in beiden Formularen...

    string connection = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source= " + ofd.FileName;

    soll in beiden Formularen verfügbar sein,aber natürlich nur einmal deklariert werden


    • Bearbeitet tklustig Donnerstag, 13. April 2017 13:13
    Donnerstag, 13. April 2017 13:12

Antworten

  • Hallo,

    du wirst um ein Singleton oder statische Instanz nicht herum kommen, siehe Toms Antwort.

    Eine rohe Fassung, die einen OleConnectionStringBuilder einsetzt und einige Basisprüfungen macht:

    using System;
    using System.Data.OleDb;
    using System.IO;
    
    namespace ElmarBoye.Samples.Code
    {
        public class AccessConnection
        {
            private static AccessConnection _instance = new AccessConnection();
    
            public static AccessConnection Default
            {
                get { return _instance; }
            }
    
            private AccessConnection()
            {
                // Optional Vorgabe aus den Settigs (User) 
                string defaultFileName = Properties.Settings.Default.AccessFileName;
                if (!String.IsNullOrWhiteSpace(defaultFileName) && File.Exists(defaultFileName))
                {
                    BuildConnectionString(defaultFileName);
                }
                    
            }
    
            private string _fileName; // wenn durchgängig via Settings ist die Variable nicht notwendig
            public string FileName
            {
                get { return this._fileName; }
                set
                {
                    BuildConnectionString(value);
                    _fileName = value;
                    Properties.Settings.Default.AccessFileName = _fileName;
                }
            }
    
            private string _connectionString;
            public string ConnectionString
            {
                get
                {
                    if (String.IsNullOrWhiteSpace(_connectionString))
                    {
                        throw new ArgumentNullException("ConnectionString", "Der Dateiname für die Verbindungszeichenfolge wurde nicht initialisiert.");
                    }
                    return this._connectionString;
                }
            }
    
            public OleDbConnection Connection
            {
                get { return new OleDbConnection(this.ConnectionString); }
            }
    
            private void BuildConnectionString(string fileName)
            {
                if (String.IsNullOrWhiteSpace(fileName))
                {
                    throw new ArgumentNullException("FileName");
                }
                if (!File.Exists(fileName))
                {
                    throw new IOException($"Access Datei '{fileName}' existiert nicht.");
                }
    
                var builder = new OleDbConnectionStringBuilder();
                builder.Provider = "Microsoft.Jet.OLEDB.4.0";
                builder.PersistSecurityInfo = false;
                builder.OleDbServices = -4;
                builder.DataSource = fileName;
                this._connectionString = builder.ToString();
            }
        }
    }
    

    Optional: In einem User Setting wird der verwendete Dateiname für eine spätere Verwendung gespeichert. Denkbar wäre ebenso, den Dateidialog für die Auswahl einzubinden.

    Verwendbar in etwa so:

         AccessConnection.Default.FileName = @"C:\TEMP\A00.mdb";
         string connectionString = Code.AccessConnection.Default.ConnectionString;
         var connection = AccessConnection.Default.Connection;
    

    Gruß Elmar

    Donnerstag, 13. April 2017 16:54

Alle Antworten

  • Hallo,

    deklariere die Variable global

    string connection = "";

    Nach dem OpenFileDialog setze

    connection = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source= " + ofd.FileName;

    Wenn du connection nutzt, prüfe auf Länge 0, und fange den Fehler ab. Es muss dann zuerst der OpenFileDialog gemacht sein, bevor man connection benutzen kann.

    Gruß Guido


    • Bearbeitet Guido Franzke Donnerstag, 13. April 2017 13:20 Formatierung
    Donnerstag, 13. April 2017 13:19
  • Aber das bringt doch nix.

    In dem Moment, wo ich mittels

       Form1 fm = new Form1();
       fm.Show();

    ein neues Formular erzeuge, kann ich da nicht mehr auf connection zugreifen,da es nicht bekannt ist. 

    Ein weiteres OpenFileDialog will ich doch vermeiden...


    • Bearbeitet tklustig Donnerstag, 13. April 2017 13:51
    Donnerstag, 13. April 2017 13:47
  • Zum Beispiel so:

        public class Test1
        {
            public Test1()
            {
                Global.connection = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source= " + ofd.FileName;
            }
        }
    
        public class Test2
        {
            public Test2()
            {
                string con = Global.connection;
            }
        }
    
        public static class Global
        {
            public static string connection = "";
            
        }

    Allerdings bin ich kein Freund davon, wegen Thread-Sicherheit usw.

    Eine elegantere Lösung wäre ein Singleton.

    Gruß

    Stefan


    Freiberufler im Bereich Softwareentwicklung Von der PLC und Robotik zu VB.NET & C#, vorrangig WPF und UWP

    Donnerstag, 13. April 2017 16:17
  • Hallo zusammen,

    um das klar zu stellen: In C# gibt es keine globalen Variablen.

    Das beste dürfte eine Statische Eigenschaft sein, wie von Stefan gezeigt, diese enthält stets das selbe - egal von wo aus man drauf zugreift. (BTW, etwas anders sieht es mit ThreadStatic aus.)

    Was Singleton vs Static betrifft: Link 1, Link 2, Link 3, ...
    Wenn du komplexere Einstellungen geplant hast empfehle ich dir die Verwendung eines Singleton, das kann Dinge wie die Serialisierung oder das Zurücksetzen vereinfachen.

    Thread sicher ist erstmal keine der beiden Lösungen. Da muss stets Vorsicht geboten sein.

    An deiner Stelle würde ich eine eigene Settings-Klasse implementieren, welche die Einstellungen verwaltet. So könntest du die getroffene Verbindung auch einfach fürs nächste mal speichern. Verwenden kannst du natürlich auch Anwendungseinstellungen, damit könntest du das selbst implementieren irgendwelcher statischer Dinge komplett weg lassen.


    Viele Grüße, Tom Lambert - MVP, MCC und MSP
    Wozu Antworten markieren und Posts bewerten? Klicke hier
    Nützliche Links: .NET Quellcode | C#/VB.NET Konverter | GitHub Forum Samples | Account bestätigen (Verify Your Account)
    Ich: Webseite | Facebook | Twitter | Code Snippets | GitHub

    Donnerstag, 13. April 2017 16:43
    Moderator
  • Hallo,

    du wirst um ein Singleton oder statische Instanz nicht herum kommen, siehe Toms Antwort.

    Eine rohe Fassung, die einen OleConnectionStringBuilder einsetzt und einige Basisprüfungen macht:

    using System;
    using System.Data.OleDb;
    using System.IO;
    
    namespace ElmarBoye.Samples.Code
    {
        public class AccessConnection
        {
            private static AccessConnection _instance = new AccessConnection();
    
            public static AccessConnection Default
            {
                get { return _instance; }
            }
    
            private AccessConnection()
            {
                // Optional Vorgabe aus den Settigs (User) 
                string defaultFileName = Properties.Settings.Default.AccessFileName;
                if (!String.IsNullOrWhiteSpace(defaultFileName) && File.Exists(defaultFileName))
                {
                    BuildConnectionString(defaultFileName);
                }
                    
            }
    
            private string _fileName; // wenn durchgängig via Settings ist die Variable nicht notwendig
            public string FileName
            {
                get { return this._fileName; }
                set
                {
                    BuildConnectionString(value);
                    _fileName = value;
                    Properties.Settings.Default.AccessFileName = _fileName;
                }
            }
    
            private string _connectionString;
            public string ConnectionString
            {
                get
                {
                    if (String.IsNullOrWhiteSpace(_connectionString))
                    {
                        throw new ArgumentNullException("ConnectionString", "Der Dateiname für die Verbindungszeichenfolge wurde nicht initialisiert.");
                    }
                    return this._connectionString;
                }
            }
    
            public OleDbConnection Connection
            {
                get { return new OleDbConnection(this.ConnectionString); }
            }
    
            private void BuildConnectionString(string fileName)
            {
                if (String.IsNullOrWhiteSpace(fileName))
                {
                    throw new ArgumentNullException("FileName");
                }
                if (!File.Exists(fileName))
                {
                    throw new IOException($"Access Datei '{fileName}' existiert nicht.");
                }
    
                var builder = new OleDbConnectionStringBuilder();
                builder.Provider = "Microsoft.Jet.OLEDB.4.0";
                builder.PersistSecurityInfo = false;
                builder.OleDbServices = -4;
                builder.DataSource = fileName;
                this._connectionString = builder.ToString();
            }
        }
    }
    

    Optional: In einem User Setting wird der verwendete Dateiname für eine spätere Verwendung gespeichert. Denkbar wäre ebenso, den Dateidialog für die Auswahl einzubinden.

    Verwendbar in etwa so:

         AccessConnection.Default.FileName = @"C:\TEMP\A00.mdb";
         string connectionString = Code.AccessConnection.Default.ConnectionString;
         var connection = AccessConnection.Default.Connection;
    

    Gruß Elmar

    Donnerstag, 13. April 2017 16:54
  • Dann werde ich wohl die Klasse von Elmar verwenden.

    Wie immer: Vielen Dank für die zahlreichen Posts!!

    • Als Antwort markiert tklustig Donnerstag, 13. April 2017 21:19
    • Tag als Antwort aufgehoben Stefan FalzModerator Donnerstag, 13. April 2017 21:20
    • Als Antwort markiert tklustig Freitag, 14. April 2017 07:25
    • Tag als Antwort aufgehoben Stefan FalzModerator Freitag, 14. April 2017 07:43
    Donnerstag, 13. April 2017 17:18
  • Hi,

    aus verschiedensten Gründen würde ich dich erneut bitten, die "Als Antwort markieren" Funktion so einzusetzen, wie sie gedacht ist, nämlich, um das oder die Posting(s) zu markieren, das oder die die Antwort(en)/Lösungen für deine Frage(n) beinhalten.

    Es macht für niemanden Sinn, dein eigenes Abschlussposting als Lösung zu markieren, wenn dort keinerlei Lösung enthalten ist.

    Da Du dich hier für Elmars Lösungsvorschlag entschieden hast, wäre es daher am hilfreichsten (auch für andere User, die irgendwann mal über diesen Thread stolpern weil Sie das gleiche oder ein sehr ähnliches Problem haben), sein Posting als Antwort zu markieren. Ich habe das in diesem Fall jetzt so gemacht.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Freitag, 14. April 2017 07:48
    Moderator
  • Uuuups. Sorry. Wußte schlichtweg nicht, dass diese Option Userbezogen ist;ging vielmehr davon aus,dass es sich auf den Thread als solchen bezieht. Werde das zukünftig beachten....
    Samstag, 15. April 2017 12:43