Laden...

Forenbeiträge von pegasus2 Ingesamt 120 Beiträge

27.08.2008 - 14:02 Uhr

verwendetes Datenbanksystem: <bitte immer angeben>
Hallo,

ich habe eine Frage zur Erstellung eines Common Language Runtime (CLR) Triggers. Ziel ist es, dass Änderungen in der Datenbank (Insert, Update, Delete) einen Dienst-Programm mitgeteilt werden.

Folgende Schritte wurden bisher von mir ausgeführt:

  1. Erstellung einer neuen Klasse Class_CLRTriggers mit folgenden C#-Code:

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.Sql;
using Microsoft.SqlServer.Server;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Xml;
using System.Text.RegularExpressions;

public class Class_CLRTriggers
{
  public delegate void myDelegate(int iID, string stName);
  public myDelegate onDBDataChanged_tabTasks;  

  //[Microsoft.SqlServer.Server.SqlProcedure]
  [SqlTrigger(Name = @"tabTest_InsertUpdate", Target = "[dbo].[tabTest]", Event = "FOR INSERT")]
  public static void tabTest_InsertUpdate()
  {
    int iID = 0;
    string stTaskName = "";
    string stDirectory = "";
    DateTime dtStartTime;

    SqlCommand command;    
    SqlTriggerContext triggContext = SqlContext.TriggerContext;
    SqlDataReader reader;

    switch (triggContext.TriggerAction)
    {
      case TriggerAction.Insert:
        using (SqlConnection connection = new SqlConnection(@"context connection = true"))
        {
          connection.Open();

          command = new SqlCommand(@"SELECT * from INSERTED;", connection);
          reader = command.ExecuteReader();
          reader.Read();
          iID = (int)reader["ID"];

          stTaskName = (string)reader["TaskName"];
          stDirectory = (string)reader["Directory"];
          dtStartTime = (DateTime)reader["StartTime"];
          reader.Close();

          onDBDataChanged_tabTasks(iID, stTaskName);//Verweis auf Methode im Dienst-Programm
          
          command = new SqlCommand(@"INSERT [dbo].[tabTest1] (TaskName,Directory,StartTime) "
            + @"VALUES (@TaskName,@Directory,@StartTime);", connection);

          command.Parameters.Add(new SqlParameter("@TaskName", stTaskName));          
          command.Parameters.Add(new SqlParameter("@Directory", stDirectory));
          command.Parameters.Add(new SqlParameter("@StartTime", dtStartTime));

          command.ExecuteNonQuery();

          break;
        }
      case TriggerAction.Update:
        command.CommandText = new SqlCommand(@"SELECT * from " + "inserted", connection);
        reader = command.ExecuteReader();
        iID = (int)reader["ID"];
        //...
        
        break;

      case TriggerAction.Delete:
        command.CommandText = new SqlCommand(@"SELECT * from " + "deleted", connection);
        reader = command.ExecuteReader();
        //...

        break;
    }
  }

  1. Erstellung einer Assembly im Verzeichnis C:\WINDOWS\Microsoft.NET\Framework\v3.5, danach Aufruf von
    C:\WINDOWS\Microsoft.NET\Framework\v3.5\csc /target:library Class_CLRTriggers.cs

  2. Bekanntmachen der Assembly in MS-SQL Server 2005:


USE [DB_Test]
      GO
      CREATE ASSEMBLY Class_CLRTriggers from 
      'C:\WINDOWS\Microsoft.NET\Framework\v3.5\Class_CLRTriggers.dll'
      WITH PERMISSION_SET = SAFE

  1. Erzeugen des Triggers mit folgenden SQL-Befehl:

USE [DB_Test]
      GO
      CREATE TRIGGER CLRTrigger
      ON dbo.tabTest
      FOR INSERT
      AS
      EXTERNAL NAME Class_CLRTriggers.Class_CLRTriggers.tabTest_InsertUpdate

  1. Dienst-Programm:
    Assembly wird unter Verweise hinzufügen dem Dienst bekannt gemacht.

In der Methode Load-Data wird folgende Zeile ausgeführt:

Class_CLRTriggers.onDBDataChanged_tabTest = new Class_CLRTriggers.myDelegate(DataChange_tabTest);

Deklarieren der Methode


public void DataChange_tabTest(int iID, string stName)
{
  //...
}

im Dienst-Programm.

Schreiben in Datenbank erfolgt mit CLR-Trigger, das würde aber auch mit T-SQL funktionieren. Problem ist die statische Methode "tabTest_InsertUpdate()", hier gelinkt es mir nicht den "Delegaten" zu verankern.
Hat jemand eine Idee, wie ich im Dienst-Programm auf DB-Ereignisse reagieren kann? Freue mich auf Anregungen von Euch.

27.08.2006 - 13:55 Uhr

Hallo herbivore,

vielen Dank für Dein Stichwort Rekursion. Hier die Lösung für meinen Anwendungsfall.


      
      private void but_Suche_Click(object sender, EventArgs e)
      {
        Rekursion(this);  
      }

      /// <summary>
      /// Es werden alle TextBoxen + Labels gesucht und mit Texten 
      /// aus der xml-Datei versehen.
      /// </summary>
      /// <param name="control"></param>
      private void Rekursion(Control control)
      {
        string stTextBox_Name = "tB_1";
        string stLabel_Name = "lab_1";

        foreach (Control ctrl in control.Controls)
        {
          if (ctrl is Label)
          {
            if (ctrl.Name == stLabel_Name)
            {
              ctrl.Text = "Label_Text";
            }
          }
          else
            Rekursion(ctrl);

          if (ctrl is TextBox)
          {
            if (ctrl.Name == stTextBox_Name)
            {
              ctrl.Text = "TextBox_Text";
            }
          }
          else
            Rekursion(ctrl);  
        }
      }

Hat auch für alle Unterebenen funktioniert!

  • ab .NET 2.0 geht: this.Controls ["myname"]

Habe im Moment leider nur das 1.1.

Grüße pegasus2

27.08.2006 - 10:45 Uhr

Hallo C-Sharpler,

ich möchte bereits bestehenden Controls (TextBox oder Label) Texte zuordnen. Die Namen der TextBoxen bzw. Labels sind mir bei Programmstart bekannt und werden beispielsweise aus einer XML-Datei gelesen.
Folgende Lösung:


        string stTextBox_Name = "tB_1";
        string stLabel_Name = "lab_1";
        for (int I = 0; I < Controls.Count; I++)
        {
          if (Controls[I] is TextBox)
          {
            if ((Controls[I] as TextBox).Name == stTextBox_Name)
            {
              Controls[I].Text = "TextBox_Text";
            }
          }
          if (Controls[I] is Label)
          {
            if ((Controls[I] as Label).Name == stLabel_Name)
            {
              Controls[I].Text = "Label_Text";
            }
          }
        }


Was mir allerdings hierbei nicht gefällt ist dass alle möglichen Controls durchlaufen werden müssen. Liegen Controls eventuell auf einem Panel muss mit Controls_.Controls[K] gearbeitet werden. Gibt es eine Möglichkeit, direkt Eigenschaften für Controls zu setzen?

Grüße von pegasus2

12.08.2006 - 13:54 Uhr

Hallo MarsStein,

Danke für die schnelle Hilfe. So funktioniert es:


listBox.Items.AddRange((string[])arr);

Ich brauchte nur einen Denkanstoß, glaube ich habe die letzte Zeit zu viel vor'm Rechner gesessen.

Grüße pegasus2

12.08.2006 - 13:17 Uhr

Hallo,
habe ein kleines Problem mit der Zuweisung eines Arrays in eine ListBox: Dazu folgender Code:


  Array arr = Array.CreateInstance(typeof(string),3);
  arr.SetValue("A",0);
  arr.SetValue("B", 1);
  arr.SetValue("C", 2);
  listBox1.Items.Add(arr);

In der ListBox erscheint dann String[] Array. Über eine Schleife kann ich die Werte auch einzeln zuweisen, könnte aber bei großen Daten zu lange dauern.

Grüße von pegasus2

22.05.2006 - 18:55 Uhr

Was wäre denn mit Framework 2.0 und SQL Server 2005? Domainbox hat leider nur den alten Server, ist von den Kosten aber auch kaum zu schlagen. Wäre vielleicht an eine günstige Alternative interessiert.

Grüße

pegasus2

22.05.2006 - 18:46 Uhr

Ich habe mit Camtasia sehr gute Erfahrungen gemacht, ist allerdings auch nicht ganz billig.

Grüße

pegasus2

22.05.2006 - 16:22 Uhr

Hallo Sandman,

versuche es mal mit

public class CryptoTest

Grüße

pegasus2

21.04.2006 - 22:56 Uhr

Hallo Dani,

zum Auslesen der Tabellenfelder würde ich lieber die 2. Überladung von dataGridView1[?,?] benutzen, da sich die Reihenfolge der Spalten mal ändern kann. Nur über den Index zu lesen ist eigentlich schlechter Programmierstil.
(hatte das Beispiel gerade zur Hand, Cell_Click ist wahrscheinlich eher ungünstig)


private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
  int iRowIndex = e.RowIndex;
  tB_Spaltenname.Text = (string)dataGridView3["Spaltenname", iRowIndex].Value;
}

Wenn Du einzelne Spalten in einer Tabelle nicht zum editieren freigeben möchtest, setze


...
  int iRowIndex = e.RowIndex;
  DataGridViewRow row = dataGridView1.Rows[iRowIndex];
  row.Cells["Spaltenname"].ReadOnly = true;
...

Grüße

pegasus2

20.04.2006 - 16:12 Uhr

Hallo phunkydizco,

warum führst Du nicht einfach 2 Felder "OnUpdate" bzw. "OnInsert" ein, die dann mit Zeitstempeln belegt werden. So kannst Du einfach über eine Abfrage herausbekommen, welche Datensätze sich zuletzt geändert haben. Wenn Du es ganz genau haben willst, kannst Du jede Änderung über einen Trigger mitprotokollieren lassen, der die geänderten Datensätze in einer zusätzlichen Tabelle speichert.

Diese Tabelle wird dann mitunter sehr groß und trägt nicht gerade zur Performance bei, kann aber in regelmäßigen Abständen immer wieder gelöscht werden.

Grüße pegasus2

14.04.2006 - 17:23 Uhr

Hallo Robert,

vielen Dank für die ausführliche Antwort. Ich habe jetzt mein Problem auch ohne die autonome Transaktion und Commit gelöst. Es kam wohl nur auf das Ereignis BEFORE INSERT an. Ist natürlich eine gute Idee, das ganze innerhalb eines Package zu deklarieren, habe mich aber jetzt doch für die einfache Lösung entschieden.

Das mit dem dbo kam beim anonymisieren bzw. vereinfachen des Code's, da ich die letzten 2 Monate mehr mit MS SQL gearbeitet habe.

Ich habe Deinen Link auf die Seite www.allroundautomations.com nochmal zum Anlass genommen, mir das Tool PL/SQL Developer runterzuladen. Funktioniert tadellos, gerade bei etwas größeren Code-Projekten echt ein Vorteil, wenn man debuggen kann. Hatte mir vor Jahren schonmal ein ähnliches Tool runtergeladen, habe aber immer die Ausgaben dafür gescheut. Zur Zeit wird es für 180 US$ angeboten, vielleicht doch eine gute Investition.

Viele Grüße

pegasus2

13.04.2006 - 21:48 Uhr

Hallo,

ich kann mich der Meinung nur anschließen. Ich würde Access nur einsetzen, um vielleicht meine private Plattensammlung oder einige wenige Kochrezepte zu verwalten. Leider zwingen mich meine Kunden immer wieder, auch etwas für Access anzubieten, da diese gerne selbst ein bischen programmieren und sich bei der Kundschaft immer jemand findet, der sich ein wenig mit Access auskennt. Aber schließlich wollen wir ja auch von etwas leben. Bei Access bin ich jedenfalls dauernd an irgendwelche Grenzen gestossen und man musste schon sehr erfindungsreich sein, dass es am Ende so funktionierte wie gewollt.

Ich finde daher der Einstieg zum MS SQL Server 2005 Express gar nicht so schlecht. Man kann kostenlos erste Erfahrungen mit einer richtigen Datenbank sammeln, der Umstieg, beispielsweise auf Oracle oder SQL 2005, ist dann auch nicht so schwer.

Der Umstieg zu DOT.NET muss sowieso irgendwann gemacht werden (will man weiterhin mit Windows arbeiten), je eher man sich darauf einstellt, desto besser.

Grüße

pegasus2

13.04.2006 - 19:20 Uhr

Hallo,

nach einigen nachdenken konnte ich das Problem lösen. Ich habe den Trigger AFTER_INSERT von "AFTER INSERT" auf "BEFORE INSERT" umgestellt.

In der Procedure INSERT_Schicht habe ich nach den SQL-Statements SELECT.. und INSERT... der inneren Schleife noch ein COMMIT gesetzt. Das wird mir ja durch setzen von "PRAGMA AUTONOMOUS_TRANSACTION" ermöglicht.

Jetzt funktioniert es genau so wie ich es brauche, hat mir auf jeden Fall viel Arbeit erspart da jede Maschine maximal ein aktiven Auftrag verwalten kann.

Grüße

pegasus2

13.04.2006 - 15:00 Uhr

Hallo,
eigentlich kein C#-Sharp Problem, aber vielleicht ist ja der eine oder andere Oracle-Spezialist unter Euch.
ich habe folgendes Problem:

Beim Einfügen eines Datensatzes in Tabelle tbSCHICHT möchte ich eventuell
weitere Einträge in diese vornehmen können. Über den Trigger "AFTER_INSERT" rufe ich die Procedure
"INSERT_SCHICHT" auf. Diese durchsucht die Tabelle tbAUFTRAG_Z nach weiteren Datensätzen, die den
geforderten Kriterien genügen und werden dann ebenfalls in Tabelle tbSCHICHT eingefügt. Beim erneuten Einfügen
stossen diese natürlich den Trigger erneut an (Rekursion), aber es werden keine weiteren Datensätze
(iTerminal ist für diese dann immer 0) gefunden. Also liegt somit auch keine echte Rekursion vor.

Mir ist schon klar, dass diese Vorgehensweise nicht ganz unproblematisch ist, aber wie kann ich
mit Tabelle tbSCHICHT gleichzeitig etwas suchen bzw. einfügen.


CREATE PROCEDURE dbo.INSERT_SCHicht
(
  pID NUMBER  
)
IS 
  PRAGMA AUTONOMOUS_TRANSACTION;
  iID        number(10,0); /*iID vom einfügenden Datensatz in Tabelle SCHICHT*/
  iID_S      number(10,0);
  vAuftrag      VARCHAR2(32);
  CURSOR cur_auftrag_zus IS SELECT * FROM tbAUFTRAG_Z WHERE AufID = pID AND iTerminal = 1;
  row_atv_zus cur_auftrag_zus%ROWTYPE; 
  CURSOR cur_insert IS SELECT * FROM tbAUFTRAG_Z WHERE AufID_Terminal = pID AND iTerminal = 0;
  row_insert cur_insert%ROWTYPE;
BEGIN 
 OPEN cur_auftrag_zus; 
  loop
    FETCH cur_auftrag_zus INTO row_atv_zus;
    EXIT WHEN cur_auftrag_zus%NOTFOUND;
    iAufID := row_atv_zus.AufID;
    OPEN cur_insert;   
    LOOP
      FETCH cur_insert INTO row_insert;
      EXIT WHEN cur_insert%NOTFOUND;
      iID_S := row_insert.AufID;
      SELECT AUFTRAG INTO vAuftrag FROM tbAUFTRAG WHERE AufID = iID_S; 
      INSERT INTO tbSCHICHT (AUFID) VALUES (iID_S); 
    END LOOP; 
    CLOSE cur_insert;
  END LOOP;
  CLOSE cur_auftrag_zus;
END;

Kein Fehler bei Abfrage "SELECT * FROM user_errors aber beim einfügen eines Test-Datensatzes erscheint folgender Fehler:

ORA-00060: Deadlock beim Warten auf Ressource festgestellt
ORA-06512:in "dbo.AFTER_INSERT", Zeile 5
ORA-04088: Fehler bei der Ausführung von Trigger 'dbo.AFTER_INSERT'


CREATE OR REPLACE TRIGGER dbo.AFTER_INSERT AFTER INSERT 
ON dbo.tbSCHICHT
FOR EACH ROW 
DECLARE 
  iID        number(10,0); /*AufID vom einfügenden Datensatz in Tabelle tbSCHICHT*/ 
BEGIN
  iID := :NEW.AUFID;
  INSERT_SCHICHT(iID);
END;

Grüße

pegasus2

30.03.2006 - 15:04 Uhr

Ich glaube nicht, dass es an der Pfadangabe liegt. Das Bild wird bei den anderen Seiten ja auch gefunden und hier ist der gleiche Code wie beim Login. Wenn ich mit dem Zurück-Button des Browsers wieder auf die Login-Seite gehen, wird die Seite korrekt dargestellt. Wenn ich jedoch auf "Abmelden" klicke springe ich wieder zur Anmeldung aber wieder ohne Hintergrund.

30.03.2006 - 14:22 Uhr

Hallo Waschbecken,

vielen Dank für die schnelle Antwort. Das ist mir so schon klar, die anderen Seiten werden aber nach genau dem gleichen Prinzip korrekt dargestellt. Ist die relative Lage beim LogIn anders und wenn ja wie kann ich das Problem lösen?

Grüße pegasus2

30.03.2006 - 13:52 Uhr

Hallo,

ich möchte gerne in meine Anmeldeseite ein Hintergrund-Bild laden. Bisher habe ich mich bei solchen Arbeiten immer auf die mitgelieferten HTML bzw. JavaScript-Generatoren verlassen und nur ab und zu nachgebessert, etwa meta-Einträge hinzufügen usw.

VS 2005 legt beispielsweise folgende Zeilen an:

<body background="Images/Hintergrund1.jpg">
<form id="form1" runat="server">
<div style="left: 10%; width: 80%; position: absolute; top: 0px; background="Images/Hintergrund1.jpg">
<br />
...
Wenn ich wieder zurückspringe auf diese Seite wird manchmal dann doch der Hintergrund korrekt dargestellt, ist für mich aber nicht ganz nachvollziehbar.

Im Editor wird "background" mit folgender Meldung "grün gewellt" untermalt: "Attribut background is considered outdated. A newer
construct is recommended.

Also habe ich folgende Änderung eingefügt:

<body style= "background-image:url(Images/Hintergrund_Hellblau_hell1.jpg)">
<form id="form1" runat="server">
<div style="left: 10%; width: 80%; position: absolute; top: 0px; background-image: url(Images/Hintergrund_Hellblau_hell1.jpg);">
<br />

Dadurch ändert sich aber auch nichts. Außerdem muss ja "deprecated" nicht sofort bedeuten, dass es generell nicht mehr funktioniert, ist halt nur veraltert.

Kann es vielleicht an meinem LogIn legen, dass zu diesem Zeitpunkt noch nicht alle Informationen dem Browser bekannt sind?

Ich benutze die neue LogIn-Komponente (mit Session) und habe damit nur gute Erfahrungen gemacht.

Edit: Die anderen Seiten funktionieren nach dem gleichen Prinzip und werden alle korrekt dargestellt. Beim Webhoster wird das LogIn mit Hintergrund auch korrekt angezeigt, da aber nicht überall DSL verfügbar ist muss ich die Web-Applikationen auch lokal auf einen Rechner laufen lassen können.

Grüße

pegasus2

28.03.2006 - 14:34 Uhr

Hallo Juergen_190,

das war jetzt ein schlechtes Beispiel. Bei MS-SQL wird die ID automatisch erzeugt (Primary Key muss gesetzt werden), bei Oracle kannst Du die ID mittels Sequenzen automatisch erzeugen. War jetzt nur ein beispiel, wie generell String und Number-Variablen behandelt werden können.

Grüße

pegasus2

28.03.2006 - 13:45 Uhr

Ach so, wem es interessiert, wer dass Duell gewonnwn hat hier die Zeiten für 1000 Einträge für Name und Vorname:

                   1. Versuch / 2. Versuch  

MS-SQL 2005: 0,90625 sec / 1,125 sec
Oracle 10g-R2: 1,01565 sec / 1,0781 sec

Grüße

pegasus2

28.03.2006 - 13:22 Uhr

Hallo juergen_190,

Thread-Wiederholung, siehe dazu auch Deine andere Anfrage:


    string strSqlCmd = "INSERT INTO Adressen (ID,Name,Vorname) VALUES (:ID,:Name,:Vorname)";
    ...   ...
    command.Parameters.Add("ID", System.Data.OracleClient.OracleType.Number).Value = iID;
    command.Parameters.Add("Name", System.Data.OracleClient.OracleType.VarChar).Value = stName;
    command.Parameters.Add("Vorname", System.Data.OracleClient.OracleType.VarChar).Value = stVorname;

Grüße

pegasus2

28.03.2006 - 13:07 Uhr

Hallo Juergen_190,

ich habe Deinen Code etwas abgeändert, so wird es funktionieren:


      DateTime date1 = DateTime.Now;
      DateTime date2 = DateTime.Now;

      System.Data.OracleClient.OracleConnection connection = new System.Data.OracleClient.OracleConnection();
      connection.ConnectionString = "Data Source=orcl;User Id=PPS;Password=geheim;Integrated Security=no";      
      string strSqlCmd = "INSERT INTO Adressen (ID,Name,Vorname) VALUES (:ID,:Name,:Vorname)";
      System.Data.OracleClient.OracleCommand command = new System.Data.OracleClient.OracleCommand(strSqlCmd, connection);

      try
      {
        connection.Open();
        string stName = "????";
        string stVorname = "Peter";
        int iID = 0;
        
        int n = 0;
        command.Parameters.Add("ID", System.Data.OracleClient.OracleType.Number).Value = iID;
        command.Parameters.Add("Name", System.Data.OracleClient.OracleType.VarChar).Value = stName;
        command.Parameters.Add("Vorname", System.Data.OracleClient.OracleType.VarChar).Value = stVorname;
        for (n = 0; n < 110; n++)
        {
          command.ExecuteNonQuery();
        }
        connection.Close();
        date2 = System.DateTime.Now;
        System.TimeSpan diff1 = date2.Subtract(date1);
        MessageBox.Show("Fertig " + " Dauer in s: " + diff1.TotalSeconds.ToString());        
      }
       catch (Exception ex)
       { 
         MessageBox.Show("Failed to connect to data source: "+ex.Message);
       }


Bei mir wurden so die Daten erfolgreich eingetragen. 🙂

Grüße pegasus2

12.03.2006 - 14:29 Uhr

Hallo,

wieder mal ein neues Problem. Ich habe innerhalb einer MultiView eine View und dort wiederum ein System.Web.UI.WebControls.Panel eingebettet. Wenn ich dort unter rechte Maustaste "Style" und dann Register "Position" für das Panel die Werte für Height bzw. Width verändere kommt es zum Absturz meiner Entwicklungsumgebung, nichts geht mehr. Selbst das "abschießen" mit dem Task-Manager fällt dann schwer, da die Anwendung alles blockiert. Musste den Rechner schon insgesamt 4 mal neu booten.

Handelt es sich um einen bekannten Fehler? Ich benutze Visual Web Developer 2005 Express Version. Bei der Professional Version waren bereits alle Werte für Width bzw. Height korrekt eingestellt, wurden aber beim erstmaligen Aufruf von der Express Version nicht korrekt übernommen. Daher musste ich hier notwendigerweise alles neu einstellen. Oder gibt es im Funktionsumfang von Proffesional zur Express Unterschiede, dass vielleicht nicht alles unterstützt wird.

Mit kommt generell so vor, das bei der Web-Entwicklung sehr viel Ressourcen benötigt werden. Habe einen P740 mit 1GB Hauptspeicher, also garnicht mal so schlecht für ein Notebook.

Grüße

pegasus2

07.03.2006 - 09:22 Uhr

Ich hatte jedenfalls den Eindruck, nachdem ich den Listener beendet und wieder gestartet hatte und eine angemessene Zeit gewartet hatte, konnte ich auf einmal auf die DB zugreifen. Vorher ging es nicht. Oder gibts noch andere Erklärungen?

Grüße pegasus2

06.03.2006 - 22:14 Uhr

Hallo,

habe gerade festgestellt dass ich einfach nur eine gewisse Zeit nach Beenden und Neustart des Dienstes OracleOraDB10g_home1TNSListener warten muss, ca. 2 bis 3 Minuten. Was bisher immer zu ungeduldig. Die DB braucht wohl immer etwas Bedenkzeit. Kann man das Verhalten der DB irgendwie abgewöhnen, wollte eigentlich auch nach längeren Pausen immer auf die DB zugreifen können.

Grüße

pegasus2

06.03.2006 - 00:06 Uhr

Hallo,

erst mal vielen Dank für Eure Hilfe. TNSPING habe ich auch schon probiert. Wenn die DB funktioniert, verhält sich alles normal. Aber es gibt immer wieder Fälle, dass ich mich nicht auf die DB verbinden kann. Kenne mich eigentlich ganz gut aus mit Oracle, deshalb ärgert es mich besonders!

Bei Kundenpräsentationen könnte es mal peinlich werden, dann muss ich eben neu starten.... X(

Es ist natürlich schwierig das Problem zu beschreiben, die Konfiguration kann ja so falsch nicht sein, da es ja meist funktioniert.

Arbeite jedenfalls weiter daran, wenn es die Zeit zuläßt...

Edit: Könnte vielleicht auch an einem fehlerhaften Update auf die neuste DB gelegen haben???

Edit: Überprüfung der Log-Files brachte auch keine neue Erkenntnis, entweder es geht oder eben nicht, warum bleibt unklar.

Grüße pegasus2

03.03.2006 - 13:36 Uhr

Hallo,
eigentlich kein C# Problem, wage aber trotzdem mal meine Frage hier im Forum zu formulieren:
Beim Zugriff auf meine Oracle 10g-Datenbank (Version 10.1.0.2.0) erscheint manchmal der Fehler ora-12541: tns: kein listener. Nach Neustart funktioniert dann meist wieder alles.
Überprüfung der Datei listener.ora im Verzeichnis C:\oracle\product\DB_1\NETWORD\Admin finden sich folgende Einstellungen.

SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = C:\oracle\product\10.1.0\Db_1)
(PROGRAM = extproc)
)
)

LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))
)
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = WINXPHOME)(PORT = 1521))
)
)

Habe unter HOST auch mal meine IP-Adresse direkt eingegeben, sollte also kein Auflösungsproblem sein. Beenden und Neustart des Dienstes OracleOraDB10g_home1TNSListener brachte auch keine Abhilfe.
Da der Fehler aber nur ab und zu auftrat, habe ich mich nicht wirklich darum gekümmert, langsamt nervt es aber.

Hat jemand schon ähnliche Erfahrungen gemacht? Da ich noch andere Datenbanken auf meinem Notebook laufen habe (MS-SQL 2005, MySQL, PostgreSQL) könnte sich da vielleicht was zwicken?

Aufruf der Seite http://localhost:5500/em schlägt dann auch fehl. Normalerweise kann ich mich hier immer an der DB anmelden.

Grüße

pegasus2

24.02.2006 - 13:26 Uhr

Hallo Maruu,

bin auch noch am kämpfen mit den Diagrammen. Habe mir in der Zwischenzeit auch noch andere Tools angeschaut, es scheint ja eine Vielzahl von Anwendungen zu geben die sich mit dieser Thematik beschäftigen. Sparx scheint aber viele "Features" abzudecken, werde mich erst mal damit weitwer beschäftigen. Englische Bezeichnungen sind eigentlich auch kein Problem, nur wenn es immer hin und her geht zwischen deutschen und englischen Ausdrücken ist es etwas verwirrend, dann lieber bei einer Sprache bleiben.

Die Kollaboration ist meines Wissens ein Teil des Kompositionsstrukturdiagramms (Composite Structure diagrams), findest Du unter Add/Add diagramm --> Eintrag "Composite Structure". Bin aber auch kein Fachmann.

Mir fehlt noch der rote Faden, einzelne Diagrammtypen zu verstehen funktioniert ja noch, aber die Verbindung aller Typen zu einem ausgewachsenen Projekt bereitert mir noch Probleme.

Kennt vielleicht jemand ein gutes Buch zum Thema, in dem an Hand eines Praxisbeispiels die Problematik erklärt wird? Gute Onlinequellen wären natürlich auch nicht schlecht.

Grüße pegasus2

23.02.2006 - 11:40 Uhr

Genau dass ist gerade mein Problem bei Sparx. Für welche Diagramme kann überhaupt sinnvollerweise Code erzeugt werden? Bei den Klassendiagrammen ist es ja noch einfach, was ist aber bei den Anwendungsfall-, Aktivitäts-, Sequenzdiagrammen usw. Wenn ich hier was an einer Stelle ändere, müßte dies ja auch Konsequenzen bei den anderen Diagrammtypen hervorrufen. Wie wirkt sich das dann auf den Code aus?

Bin gerade dabei Code aus einem Aktivitätsdiagramm zu generieren, gelingt mir aber nicht. Hat schon jemand Erfahrungen gesammelt? Leider werden in den Lehrbücher nur die Diagrammtypen nacheinander abgehandelt, aber wenig über Interaktionen gesagt. Würde mich über Antworten freuen.

Grüße pegasus2

23.02.2006 - 11:09 Uhr

Original von pegasus2
Hallo Maruu,

ich experimentiere seit ein paar Tagen mit ObjectiF6.0 und Enterprise Architect von Sparx. Die Version von microTool in der Trial-Version ist zunächst kostenlos, allerdings vom Einsatz her begrenzt, reicht also nur zum erlernen der UML. Von Sparx gibt es eine Vielzahl von Versionen, für Studenten und Schüler soweit ich weiß auch schon unter 100,- €, dann aber auch mit Einschränkungen. Zum testen ist eine Version für 30 Tage erhältlich. Das Tool von Sparx bietet mit die meisten "Features".

ObjectiF hat den Vorteil einer recht umfassenden Dokumentation in deutscher Sprache, gerade zum erlernen von UML nicht schlecht. Wikipedia hilft hier bei der Syntax auch gut weiter:


>

Andere Tools, wie etwa Rational Rose und Enterprise Architekt habe ich bisher nur in englischer Sprache gesehen.

Grüße pegasus2

23.02.2006 - 11:07 Uhr

Hallo Maruu,

ich experimentiere seit ein paar Tagen mit ObjectiF6.0 und Enterprise Architect von Sparx. Die Version von microTool in der Trial-Version ist zunächst kostenlos, allerdings vom Einsatz her begrenzt, reicht also nur zum erlernen der UML. Von Sparx gibt es eine Vielzahl von Versionen, für Studenten und Schüler soweit ich weiß auch schon unter 100,- €, dann aber auch mit Einschränkungen. Zum testen ist eine Version für 30 Tage erhältlich.

ObjectiF hat den Vorteil einer recht umfassenden Dokumentation in deutscher Sprache, gerade zum erlernen von UML nicht schlecht. Wikipedia hilft hier bei der Syntax auch gut weiter:

d

Andere Tools, wie etwa Rational Rose und Enterprise Architekt habe ich bisher nur in englischer Sprache gesehen.

Grüße pegasus2

21.02.2006 - 14:24 Uhr

So vielleicht, habs aber nicht getestet:


          DataTable dt = DataSet1.Tables["Tabelle1"];
          if (Conn.State == ConnectionState.Open)
          {
            DataRow newRow = dt.NewRow();
            newRow["AUFTRAG"] = "Auf1";
            dt.Rows.Add(newRow);            
          }

Grüße pegasus2

21.02.2006 - 13:16 Uhr

Hallo MartinR,

Du wolltest auch schreiben (habs übersehen), hier der Code:


string sqlStr = "INSERT INTO Tabelle1 (AUFTRAG) VALUES ('AUFTRAG1')";
OracleCommand cmd = null;
cmd = new OracleCommand(sqlStr, Conn);
OracleDataReader dr = cmd.ExecuteReader();

Es kann sinnvoll sein, die INSERT SQL Statements zunächst in einer Datei zu speichern. Sollte die Verbindung zur DB mal verloren gehen, kannst Du in regelmäßigen Abständen versuchen, die SQL-Statements aus der Datei in die DB zu übertragen. Da gibts aber noch andere Techniken, Aktenkofferprinzip beispielsweise.

Grüße pegasus2

21.02.2006 - 12:50 Uhr

Hallo MartinR,

habe es bei mir mal getestet. Mit folgenden Code kann ich auf die Oracle10g-Datenbank zugreifen:


OracleConnection Conn = new OracleConnection();
//Conn.ConnectionString = "Data Source=testdb;User ID=/;Integrated Security=yes;";
Conn.ConnectionString = "Data Source=orcl;Persist Security Info=True;User ID=User;Password=geheim;Unicode=True";
Conn.Open();
            
OracleDataAdapter adapter = new OracleDataAdapter("Select * from Tabelle1", Conn);            
DataSet DataSet1 = new DataSet();
adapter.Fill(DataSet1, "Tabelle1"); 
            
string sqlStr = "SELECT * FROM Tabelle1 ORDER BY ID";
OracleCommand cmd = null;
cmd = new OracleCommand(sqlStr, Conn);
OracleDataReader dr = cmd.ExecuteReader();
string stAuftrag = "";
while (dr.Read())
{
  stAuftrag = dr["Auftrag"].ToString();
}

Es kommt keine Fehlermeldung, Daten werden korrekt angezeigt.

Grüße von pegasus2

15.02.2006 - 21:19 Uhr

Hallo DeveloperX,

wenn Du schon die Freiheit hast, dir ein Diplom-Thema selbst suchen zu können, würde ich mir vielleicht Anregung bei potentiellen Arbeitgebern suchen. Bei genauer Recherche kristallisieren sich bestimmt interessante Themenschwerpunkte heraus. Meine Erfahrung zeigt, dass eine passende Diplom-Arbeit spätere Verhandlungen im Einstellungsgespräch wesentlich erleichern können.

Grüße pegasus2

15.02.2006 - 13:30 Uhr

Hallo, ich habe einen ganz guten Vergleichsartikel verschiedener UML-Tools gefunden:

http://www.big.tuwien.ac.at/teaching/practicals-diplomatheses/bachelor/doc/uml2_tools_0511.pdf

Grüße pegasus2

03.02.2006 - 15:43 Uhr

Hallo Golo,

User instance = false:
Ein Wert, der angibt, ob die Verbindung von der Standardinstanz von SQL Server Express auf eine von der Laufzeit initiierte Instanz umgeleitet werden soll, die unter dem Konto des Aufrufers ausgeführt wird.

Quelle:

http://msdn2.microsoft.com/de-de/system.data.sqlclient.sqlconnection.connectionstring.aspx

Kannst Du was damit anfangen?

Grüße von pegasus2

31.01.2006 - 16:51 Uhr

Hallo Tokka,

stimmt, Du hast Recht. Hatte es bei mir eingefügt, da ich vor Jahren einen eigenen DB-Manager für Oracle programmiert hatte. Diente nur der Übersichtlichkeit.

Gruß pegasus2

31.01.2006 - 15:03 Uhr

Hallo MartinR,

versuche es mal damit:

CREATE TABLE Tab1 ( ID NUMBER(*) CONSTRAINT pk_id PRIMARY KEY, Vorname VARCHAR2(15), Name VARCHAR2(15) );

CREATE TABLE Tab2 (
ID NUMBER(*) PRIMARY KEY,
Vorname VARCHAR2(15),
Name VARCHAR2(15)
);

Als Trennzeichen immer "---" einfügen, dann können auch mehrere SQL-Statements behandelt werden. Wenn Du direkt mittels CONSTRAINT einen Namen angibts, wird dieser so in der DB angelegt. Ansonsten erzeugt ORACLE einen automatisch generierten Namen, der dann nicht so aussagekräftig ist. PRIMARY KEY-Felder werden spätestens bei der Verknüpfung von Tabellen benötigt, also am besten gleich mit anlegen. Stichwort: referentielle Integrität

Viele Grüße

pegasus2

27.01.2006 - 01:01 Uhr

Hallo Meti,

habe gerade mal eine ähnliche Abfrage mit den Komponenten DataSet, BindingSource, TableAdapter und BindingNavigator ausprobiert. In Komponente BindingSource habe ich der Eigenschaft Filter folgenden Code zugefügt:


DateTime dDatum1 = DateTime.Now;
DateTime dDatum2 = DateTime.Now.AddDays(30);
adressenBindingSource.Filter = "[Zeit_V] > '"+dDatum1+"' AND [Zeit_B] < '"+dDatum2+"'";

Bei mir hat es funktioniert. Vielleicht hilft es Dir weiter.

Viele Grüße

pegasus2

23.01.2006 - 21:42 Uhr

Hallo Curse4Life,

hier ein kurzes Beispiel:

INSERT INTO dbo.Adressen (Name)
OUTPUT INSERTED.* VALUES ('Thomas')
SELECT @@IDENTITY AS [@@IDENTITY], SCOPE_IDENTITY() AS [SCOPE_IDENTITY]

SCOPE_IDENTITY und @@IDENTITY geben die letzten Identitätswerte zurück, die in einer beliebigen Tabelle in der aktuellen Sitzung generiert wurden. SCOPE_IDENTITY gibt jedoch nur im aktuellen Gültigkeitsbereich eingefügte Werte zurück, @@IDENTITY ist nicht auf einen bestimmten Gültigkeitsbereich begrenzt.

Siehe auch.

http://msdn2.microsoft.com/de-de/ms190315.aspx

Grüße pegasus2

23.01.2006 - 20:25 Uhr

Hallo Nightline,

habe mir vor ein paar Monaten die gleiche Frage gestellt, ASP.Net-Webseiten inclusive DB-Zugriff vom heimischen PC aus zu hosten.

  1. Über www.DynDNS.com kannst Du Dir dort Deine aktuelle IP-Adresse verwalten lassen. Ich habe es bei mir über den Router konfiguriert; wird die Verbindung unterbrochen, wird automatisch bei DynDNS der geänderte Eintrag der IP-Adresse geführt und Du bist somit immer erreichbar. Gibt dort nur keine so schöne Namen.
  2. Anschließend muss natürlich der Internet-Information-Server (IIS) konfiguriert werden.
  3. Danach kann recht einfach der Zugriff auf DB mittels Web Developer programmiert werden.

Zugegeben, man muss sich ein bischen durchbeissen, mittlerweile gibt es aber viele brauchbare Dokus (siehe beispielsweise hier im Forum). Habe es letztendlich auch hinbekommen, war für mich auch nur eine kleine Übung. Bei kommerziellen Anwendungen bist Du wahrscheinlich bei einen professionellen Anbieter eh besser aufgehoben, alleine schon wegen der Ausfallsicherheit usw. wenn Du nicht all zu viel Geld in die Hardware investieren möchtest.

Grüße pegasus2

22.01.2006 - 23:55 Uhr

Hallo trinkjoghurt,

habe noch eine andere Quelle gefunden unter

http://msdn2.microsoft.com/de-de/ms146869(de-de,SQL.90).aspx

Hier wird eine Lösung mit dem neuen Programmiermodell RMO (=Replication Management Objects) beschrieben. Danach hatte ich eigentlich gesucht. Bei dieser Lösung wird allerdings mit Assemblies der zu nutzenden Datenbank gearbeitet, so müssen z.B. Assemblies unter C:\Program Files\Microsoft SQL Server\90\SDK\Assemblies oder \COM eingebunden werden: Microsoft.SqlServer.Replication.dll und Microsoft.SqlServer.Replication.BusinessLogicSupport.dll. Damit ist dieser Ansatz sicherlich nicht datenbankunabhängig.

Kennst Du die Vorteile/Nachteile der verschiedenen Lösungen?

Habe mal den Beispiel-Code hergenommen und stolpere auch gleich über die erste Hürde:


using Microsoft.SqlServer.Replication;//Pfad C:\Program Files\Microsoft SQL Server\90\SDK\Assemblies -->Browse Assembly Microsoft.SqlServer.Replication.dll 
using Microsoft.SqlServer.Management.Common;
// This namespace is only used when creating custom business
// logic for merge replication.
using Microsoft.SqlServer.Replication.BusinessLogicSupport;//Browse Assembly Microsoft.SqlServer.Replication.BusinessLogicSupport.dll
...
private void button1_Click(object sender, EventArgs e)
{
  string publisherName = "WINXPHOME\\SQLEXPRESS";
  //string publisherName = "81.201.105.30";
  string publicationName = "Verwaltung";
  string publicationDbName = "Verwaltung";

  ReplicationDatabase publicationDb;
  MergePublication publication;
  // Create a connection to the Publisher.
  ServerConnection conn = new ServerConnection(publisherName);

   try
     {
        // Connect to the Publisher.
        conn.Connect();

        // Enable the database for merge publication.                
        publicationDb = new ReplicationDatabase(publicationDbName, conn);
        if (publicationDb.LoadProperties())
        //hier kommt der Fehler
          {
             if (!publicationDb.EnabledMergePublishing)
               {
                  publicationDb.EnabledMergePublishing = true;
                }
           }
           else
             {
                // Do something here if the database does not exist. 
                throw new ApplicationException(String.Format(
                 "The {0} database does not exist on {1}.",
                 publicationDb, publisherName));
              }
        ...
   catch
    {
      ...
    }
}

Grüsse von pegasus2

22.01.2006 - 17:43 Uhr

Hallo,

ich möchte gerne eine lokale Datenbank mittels Merge (DataSet.Merge() ) mit der Hauptdatenbank abgleichen könnnen. Änderungen auf dem Notebook sollen bei Verbindung mit der Haupt-SQL Datenbank übertragen werden. Dazu befindet sich auf dem lokalen Rechner (Notebook) eine DB Verwaltung.mdf.

Ich arbeite lokal mit SQL Server Management Express Studio und Visual C# 2005 Express Studio. Die Haupt-Datenbank kann dabei durchaus ein vollwertiger SQL Server sein.

Im Management Express Studio habe ich die Möglichkeit, die Hauptdatenbank mittels IP-Adresse zu konfigurieren. Im Visual C# Express Studio vermisse ich diese Möglichkeit, auf die Haupt-Datenbank zugreifen zu können.

Muss ich auf jeden Rechner (Notebook) eine Client-Installation vornehmen (was ich eigentlich vermeiden wollte)? Wie sieht es dann mit Lizenzkosten aus?

Edit: Habe bisher nur mit echten Client-Lösungen gearbeitet. Ich wollte für einen nicht so ganz zahlungskräftigen Kunden eine Lösung auf Basis der Express Edition anbieten.

Grüsse pegasus2

21.01.2006 - 14:29 Uhr

Hallo Programmierhans,

schau Dir mal diesen WebCast dazu an, ich denke er erklärt Dein Problem ganz gut.
https://www.microsoft.com/germany/msdn/webcasts/library.aspx?id=118764792

Grüsse von pegasus2

21.01.2006 - 14:18 Uhr

Hallo Druid,
vielen Dank für die Antwort. Habe jetzt mal die Dienste für SQL Server(SQLExpress) + SQL Server(MSSQLServer) beendet. Danach die Entwicklungsumgebung für Microsoft Visual C# 2005 Express Edition aufgerufen. Danach werden mir im Database Explorer wieder die Datei Verwaltung.mdf mit den Einträgen Database Diagrams, Tables, Views,...usw. angezeigt. Im Microsoft SQL Server Management Studio Express (immer diese langen Namen) jedoch nicht.

Vermutlich liegt es daran dass ein gleichzeitiger Zugriff auf die Datei Verwaltung.mdf nicht vorgesehen ist.

Grüsse pegasus2

20.01.2006 - 12:10 Uhr

Nachdem ich den Rechner neu gestartet habe, wieder der umgekehrte Fall: Im Database Explorer kann ich auf die Datenbank zugreifen jedoch nicht mittels Microsoft SQL Server Management Studio Express Edition.

Hierzu folgende Fehlermeldung.

Unable to open the physical file "c:\Programme\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\Verwaltung.mdf". Operating system error 32: "32(Der Prozess kann nicht auf die Datei zugreifen, da sie von einem anderen Prozess verwendet wird.)". (.Net SqlClient Data Provider)

Edit:
Nachdem ich die C# Express Edition beendet habe folgende Fehlermeldung:

Database 'Verwaltung' cannot be opened due to inaccessible files or insufficient memory or disk space. See the SQL Server errorlog for details. (.Net SqlClient Data Provider)

Gerade ging es aber noch, ist also abhängig von der Startreihenfolge der Programme.

Grüsse von pegasus2

20.01.2006 - 11:24 Uhr

Ich habe ein Problem beim parallelen Zugriff auf die SQL Datenbank. Nachdem ich gestern vergeblich versucht habe mittels Microsoft SQL Server Management Studio Express zuzugreifen (Zugriff mit Database Explorer vom Visual C# 2005 Express Edition funktionierte bereits) heute genau das umgekehrte Problem. Ich habe heute zuerst die Verbindung mittels Microsoft SQL Server Management Studio Express aufgebaut, klappte auf Anhieb. Danach kam ich aber nicht mehr auf die Datenbank über den Database Explorer. Auch nachdem ich die Verbindung des SQL Server Management Studio Express zur Datenbank unterbrochen hatte, kam ich nicht mehr auf die Datenbank über den Database Explorer.

Ich habe bisher nur mit der Professional Version von Visual C# 2005 und den SQL Server 2005 Enterprise Edition gearbeitet und wollte mal die Express-Versionen ausprobieren.

Wie sieht es mit den Lizenzen aus bei den Express Versionen? Ich benötige eine zentrale Datenbank die von den Kundendienstlern, die eine lokale Datenbank mitführen, immer wieder aktualisiert werden müsste.

Grüsse von pegasus2

18.11.2005 - 17:07 Uhr

Hallo,

ich setze ein DropDownList-Control ein und möchte gerne auf ein OnClick-Ereignis reagieren. Leider wird mir vom Control nur ein SelectIndexChanged-Ereignis angeboten. Wenn zufällig der erste Eintrag ausgewählt wird, wird somit kein Ereignis ausgelöst (Index wurde ja auch nicht verändert) hätte aber gerne eins.
Kann mir jemand helfen?

Ich könnte natürlich an der ersten Stelle einen leeren Eintrag vornehmen, somit würde immer ein Indexwechsel ausgelöst, die Lösung gefällt mir aber auch nicht so recht.

Grüße pegasus2

11.11.2005 - 13:36 Uhr

So besser? 🙂

Ich dachte erst, es wäre ein Fehler.

Grüsse pegasus2

11.11.2005 - 12:41 Uhr

Hallo,

war wohl mal wieder zu voreilig gewesen, doch kein Bug! Leider raubt mir dieses Control den letzten Nerv, liegt aber mehr an der schlechten Dokumentation.

Hier also die Lösung:
Man braucht einfach nur EnableAutoPostBack von DropDownList zu aktivieren, damit auch weitere Ereignisse aufgerufen werden können. Hatte es im Eifer des Gefechts nur beim ersten Control gemacht, daher funktionierte es auch da.

Ein weiterer Effekt ist, das bei der Auswahl weiterer Einträge der DropDownLists die ersten wieder verloren gehen, eben solange, bis "Update" aufgerufen wird. Daher sollten bei jeder neuen Auswahl die bereits getroffen wurden alle vorangeganenen Einträge, die man am bessten in Session-Variablen speichert, neu zugewiesen werden.

Da sieht dann so aus:


iNewEditIndex = Session["NewEditIndex"];
GridView1.Rows[iNewEditIndex].Cells[28].Text = stNamen_ID;

Den Wert NewEditIndex holt man sich aus GridView1_RowEditing mit folgender Zuweisung:


Session["NewEditIndex"] = e.NewEditIndex;

Grüße pegasus2