Laden...

Forenbeiträge von CSharperUser Ingesamt 80 Beiträge

21.07.2011 - 20:22 Uhr

Ich habe überhaupt nicht weiter im Release-Modus getestet, sondern befinde mich immer noch im Debug-Modus.

Wie bereits gesagt, selbst im Debug-Modus bekomme ich nur die Benachrichtigung wenn ich vorher manuell in den Service debugge, sonst bekomme ich keine Benachrichtigung.

Wenn ich die Trace-Ausgaben anschaue meldet er mir folgende Aufrufe:

  1. In Connect
  2. In RegisterForEvents

Aber funktioniert hat der Code ja schon mal, aber eben nur wenn ich manuell vorher in den Service debugge.

Deshalb ist mir das Verhalten einfach nicht klar.

Kann es wie in einem früheren Post schon beschrieben, vielleicht an den ServiceBehavior-Einstellungen oder an der USeSynchronizationContext-Einstellung liegen?

Bzw. können Projekteinstellungen oder die Angabe in der App.config mit "compilation debug = true" der Grund sein?

21.07.2011 - 15:27 Uhr

Im Release-Modus hatte ich die DB-Schnittstelle in anderen Projekten (WinForms, Konsole, etc.) getestet.

Bisher will ich es einfach nur hinbekommen, dass das ganze innerhalb eines WCF-Services ohne vorherigen Step läuft (Vorerst bin ich nur im Debug-Mode).

Vielleicht hilft diese Info noch:

Die DBManager-Dll ist eine Release-Dll. Die Host-Applikation ist eine Release-Version.

Der Client und der Service sind als Debug compiliert.

Was mir auch noch einfällt:

Ich habe bei der Implementierung des Callback-Interfaces "UseSynchronizationContext" auf false stehen. Könnte das damit zusammenhängen?

21.07.2011 - 15:21 Uhr

Das Change-Event kommt unabhängig vom Build-Modus. Die Liste hat den gewünschten Eintrag und das Delegate wird auch mittels Invoke aufgerufen. Hab ich auch schon in verschiedenen Projekten ohne WCF getestet.

Und im Debug Mode mit einem Step in den Service sehe ich das auch. Nur ohne den Step geht nix.

21.07.2011 - 15:09 Uhr

Die RegisterForUpdate und Insert-Methoden nehmen das übergebene Delegate und speichern es in einer Liste. Wenn nun das Change-Event der SqlDependency kommt wird einfach der Delegate aus der Liste herausgenommen und mit Invoke aufgerufen.

Das mit dem WaitCallback vor dem ThreadPool habe ich gemacht, aber löst nicht das Problem.

Das ganze funktioniert nur, wenn ich (egal welcher Build-Modus) vorher mittels Breakpoint einmal in den Service hineingesprungen bin. Und für mich ist das einfach nicht logisch, deshalb weiß ich nicht wie ich das lösen kann.

Kann es vielleicht auch an der Config liegen? Ich habe da auf jeden Fall für das Servicebehavior "IncludeExceptionDetails" auf true und beim Tag "compilation debug" auf true.

21.07.2011 - 13:42 Uhr

Hallo gfoidl,

Folgende Dinge habe ich jetzt gemacht:

  1. Ein kleines Testprojekt, dass auf die Callbacks reduziert ist:
    Selbst hier bekomme ich keine Lösung zustande

  2. Die DB-Dll nochmals in verschiedenen Umgebungen getestet:
    Die Benachrichtigung kommt immer an

  3. Trace.Writeline überall eingefügt:
    Es wird nirgendwo eine Ausgabe angezeigt

  4. Die Db Schnittstelle im Service durch Timer ersetzt:
    Funktioniert jedes mal, egal welcher Buildmodus

Das heißt für mich, dass es weder an der DB-Schnittstelle noch an den Callbacks liegt.

Wie gesagt, wenn ich zuvor einmal in den Service reindebugge, dann funktioniert alles einwandfrei.

Tue ich das einmal nicht, funktioniert es nicht mehr.

Was macht das Debuggen anders. Ist das eventuell was Zeitliches?

Das was mich am meisten verwundert, ist dass die traces nicht ausgegeben werden, beim Debuggen aber alle Punkte erreicht werden.

Meine beiden letzten Vermutungen sind folgende:

  1. Übergabe des Delegaten für die Register-Methode kann aus irgendeinem Grund nicht aufgerufen werden im Service Context?

  2. Der ServiceHost ist eine WPF-Anwendung, die als Release-Variante läuft. Kann es vielleicht daran liegen?

20.07.2011 - 20:55 Uhr

Hallo gfoidl,

den DBManager hab ich schon mit einer Konsolenanwendung getestet, die Events kamen somit auch richtig an.

Ich wollte das ganze auch schon per call laufen lassen nur habe ich dann das problem, dass der Service somit zustandslos läuft und ich somit eine Verbindung nicht mit mehreren Clients teilen kann.

Siehst du eventuell eine Möglichkeit wie ich das PerCall gewährleisten kann?

Wie kann ich aus dem Service heraus feststellen, dass der Host geschlossen wurde?

Ich werde dann versuchen, die von dir genannten Punkte umzusetzen.

Das mit den Timern habe ich übrigens auch schon getestet. Die damit verbundenen Callbacks kommen auch bei mir an.

Ich frage mich einfach lediglich nur, dass wenn ich im Debug-Modus mittels Breakpoint in die RegisterClient-Methode steppe, ich dann auch die Callbacks für die genannte Implementierung erhalte und sonst nicht. Ich sehe dahinter einfach die Logik nicht 🤔

Kann es vielleicht auch daran liegen, dass ich den Aufruf der RegisterClient-Methode (das ist die erste Methode, die den Listener-Prozess startet) in einem asynchronen Thread laufen habe (dient zum Aufbauen der Verbindung innerhalb eines Splahscreens)?

Auf jeden Fall möchte ich mich für deine bisherige Hilfe bedanken. Durch deine Hilfe bin ich dem Ganzen schon näher gekommen. 👍

20.07.2011 - 17:39 Uhr

Hallo gfoidl,

ich finde trotz allem keinen Fehler.

Hier die Serviceimplementierung:


[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
  public sealed class ServiceImpl : IService
  {
    #region Members
    private readonly List<IServiceCallbacks> _clientCallbacks;

    private bool _isInitialized;
    #endregion


    public ServiceImpl ()
    {
      _clientCallbacks = new List<IServiceCallbacks>();
    }


    #region Methods
    public void RegisterClient()
    {
      var operationContext = OperationContext.Current;

      if (operationContext == null)
        throw new FaultException<ServiceException>(new ServiceException("OperationContext is null", null));

      if (!_isInitialized)
      {
        _isInitialized = true;

        //operationContext.Host.Closed += HostClosed;
        Connect();
        RegisterForEvents();
      }

      var clientCallback =  operationContext.GetCallbackChannel<IServiceCallbacks>();

      if (clientCallback != null)
      {
        lock (_clientCallbacks)
        {
          _clientCallbacks.Add(clientCallback);
        }
      }
    }


    public void UnregisterClient()
    {
      var operationContext = OperationContext.Current;
      if (operationContext == null)
        throw new FaultException<ServiceException>(new ServiceException("OperationContext is null", null));

      //operationContext.Host.Closed -= HostClosed;

      var clientCallback = operationContext.GetCallbackChannel<IServiceCallbacks>();

      lock (_clientCallbacks)
      {
        if (_clientCallbacks.Contains(clientCallback))
          _clientCallbacks.Remove(clientCallback);
      }
    }


    private void RegisterForEvents()
    {
      DBManager.Current.RegisterForUpdate(aUpdateGuid => 
      ThreadPool.QueueUserWorkItem(delegate
       {
           lock (_clientCallbacks)
           {
              foreach (var clientCallback in _clientCallbacks)
                       clientCallback.SendActionMessage("Update");
           }
      }));
   
      DBManager.Current.RegisterForInsert(aInsertGuid => 
      ThreadPool.QueueUserWorkItem(delegate
       {
           lock (_clientCallbacks)
           {
              foreach (var clientCallback in _clientCallbacks)
                       clientCallback.SendActionMessage("Insert");
           }
      }));
    }

    private static void Connect()
    {
      DBManager.Current.Connect();
    }


     ~ServiceImpl()
    {
      DBManager.Current.Close();
    }

Zur weiteren Info:
Beim Connect-Aufruf wird eine Verbindung zur Datenbank aufgebaut, die ich solange aufrechterhalten möchte, bis der ServiceHost geschlossen wird.
Dabi wird gleichzeitig der Listener mit dem SQLDependency-Objekt gestartet, der wiederum in einem eigenen Thread läuft und Änderungen verfolgt.

20.07.2011 - 11:01 Uhr

Hallo gfoidl,

Ich habe nun das ganze wie du sagst umgesetzt. Trotzdem besteht das Phänomen weiterhin.

Wenn ich kurz einmal in den Service per Debug reingehe, dann bekommt er den Callback.

Wenn ich keinen Breakpoint setze, dann bekomm ich den Callback nicht.

19.07.2011 - 19:07 Uhr

Hallo gfoidl,

danke für deine schnelle Antwort.

Ich mache am besten ein Beispiel:

Ich habe in der DB-Dll eine Singleton-Klasse, die folgende Methoden bereitstellt:


DBManager.Current.RegisterForInsert(Action aInsertHandle);
DBManager.Current.Connect();

Nun habe ich eine Service-Dll, die folgende Contract-Methode anbietet:


public class MyService : IService
{
   public void Initialize()
   {
       DBManager.Current.RegisterForInsert(new Action(()=> 
       {
            var proxy = 
            OperationContext.Current.GetCallbackChannel<IServiceCallback>();
            proxy.Send("Insert");
       }));
       DBManager.Current.Connect();
   }
}

Die Callback-Schnittstelle hat eine Methode


void Send(string action);

Für die Serviceklasse habe ich die Behaviours "Single" und "Multiple".

Was ich noch vergessen habe ist, dass ich als Binding "NetTcpBinding" verwende.

Wenn nun die Applikation und der Service mit dem Host laufen und ein anderer Benutzer beispielsweise über das SQLManagementStudio einen Eintrag hinzufügt, wird dies auch von der SQLDependency-Klasse erkannt und das übergebene Delegate mittels Invoke aufgerufen.

Wenn ich nun die Service-Dll als Debug-Variante hoste bekomme ich die Nachricht des Callbacks.

Wenn ich die Service-Dll als Release-Variante hoste, bekomme ich die Nachricht nicht.

P.S.: Ich habe mich eigentlich an dem von dir verlinkten Beispiel orientiert. Kann es vielleicht sein, dass es beim ServiceContract-Attribut des Callbacks am "SessionMode" liegen kann? Ich habe den SessionMode nämlich nicht angegeben.

19.07.2011 - 17:11 Uhr

Hallo Leute,

ich habe eine C#-Dll, die den Datenbank-Zugriff handelt. Innerhalb dieser Dll läuft ein Listener, der die SQL Server 2008 Datenbank mittels SQLDependency abhört und ein Event feuert, sobald eine Änderung aufgetreten ist.

Diese Dll wird in einem WCF Service aufgerufen und sich für das Event registriert.
Für die Registrierung übergebe ich der Funktion einen Delegate, der ausgeführt wird, sobald eine Änderung existiert.

Der Service wird mittels ServiceHost selbst gehostet.

Wenn ich den Service als eigene Dll als Debug-Dll hoste, kann ich reinsteppen und erhalte auch die Events.

Wenn ich den Service als Release-Dll hoste, bekomme ich keine Events.

Woran kann das liegen?

13.07.2011 - 06:31 Uhr

Hallo jahr2000fehler,

Die Exception tritt auf, weil innerhalb deiner Service-Implementierung eine Exception ausgelöst wird, die du nicht behandelst. So auf den ersten Blick habe ich zwei Vermutungen:

  1. Deine ArrayList "Korb" wirft beim Zugriff über Count eine NullreferenceException, weil keine Instanz erstellt hast

  2. Der Cast in "Product" bei (Product)korb_ geht schief, weil der Inhalt null oder einfach nicht in den Typ Product umgewandelt werden kann.

Ich würde so oder so vorschlagen, du verwendest eine generische Liste, Bsp. List<Product>, somit hast du Typsicherheit und das Casten fällt weg.

30.06.2011 - 06:41 Uhr

Hallo mygil,

Grundsätzlich ist die Vorgehensweise richtig. Wenn du Änderungen innerhalb einer Liste nicht manuell verfolgen willst, kannst du anstatt List<T> eine ObservableCollection<T> nehmen.

Bei dieser kannst du dich auf das Event CollectionChanged hängen, dass dir in den EventArgs die Action (gelöscht, geändert, neu) sowie die betroffenen Elemente liefert. Dann musst du nur die Action auswerten und entsprechend bei Neu auf die Datenbank ein insert, bei geändert ein update mit entsprechendem where-filter und bei gelöscht ein delete mit entsprechendem where-filter machen.

Eleganter geht das ganze auch mit O/R-Mappern wie dem Entity Framework.

27.04.2011 - 15:51 Uhr

Wenn du nicht motiviert bist, am Code zu arbeiten gibt es meistens mehrere Gründe:
1.) Die Aufgabenstellung unterfordert dich
2.) Der Sourcecode ist von einem anderen schlecht geschrieben und nicht
dokumentiert, sodass du den Einstieg nicht findest
3.) Das Projekt und die Aufgaben liegen dir nicht (zum Beispiel wenn du mit der Branche nichts anfangen kannst)
4.) Du bist ausgelaugt und würdest gerne an eine andere Aufgabe gehn, weil dir die derzeitige Aufgabe zum Hals raushängt.

Ich schnapp mir meist ein aktuelles Fachbuch, das ich gerade lese, und lese vielleicht ne Stunde. Danach geh ich wieder an den Code. usw.

11.03.2011 - 15:10 Uhr

Okay das Problem hat sich erledigt, ich hatte vergessen, die C# Dll in das Ausgabeverzeichnis zu kopieren.

11.03.2011 - 13:39 Uhr

Hallo zusammen,

ich habe folgendes Szenario:
Ich muss eine C# Dll für eine reine Win32 Anwendung verfügbar machen.
Nun habe ich die C# Dll in einer C++/Cli Klassenbibliothek eingebunden. Dann habe ich ein Win32 Konsolenprojekt erstellt und dort die Managed C++ lib und dll referenziert sowie den Header eingebunden.

Beim Erzeugen einer Instanz der Managed Klasse wird eine Exception geworfen.

Ich habe mich bei der Erstellung an folgendem Tutorial orientiert:
.NET to C++ Bridge

Ich verwende Visual Studio 2010 Professional.

Meine C# Dll sieht so aus:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CsTest
{
  public class Adder
  {
    public int Add(int a, int b)
    {
      return a + b;
    }
  }
}

Der Header der Bridge Klasse:


#pragma once
#pragma managed
#using <CsTest.dll>
#include <vcclr.h>

class ILBridgeAdder
{
	private:
	gcroot<CsTest::Adder^> _adder;
public:
	ILBridgeAdder(void);
	int Add(int a, int b);
};

sowie der Header der Nativen Klasse:


#pragma once
#pragma unmanaged

class ILBridgeAdder;

class __declspec(dllexport) NativeAdder
{
private:
	ILBridgeAdder* _adder;
public:
 NativeAdder(void);
~NativeAdder(void);
 int Add(int a, int b);
};

Und zuletzt die Cpps von der Bridge Klasse und der nativen Klasse:

  1. Bridge:

#include "StdAfx.h"
#include "ILBridgeAdder.h"

ILBridgeAdder::ILBridgeAdder(void)
{
	_adder = gcnew CsTest::Adder;
}

int ILBridgeAdder::Add(int a, int b)
{
	return _adder->Add(a,b);
}

  1. Nativ:

#pragma managed
#include "Stdafx.h"
#include "ILBridgeAdder.h"

#pragma unmanaged
#include "NativeAdder.h"


NativeAdder::NativeAdder(void)
{
	_adder = new ILBridgeAdder;
}
NativeAdder::~NativeAdder(void)
{
	delete _adder;
}

int NativeAdder::Add(int a, int b)
{
	return _adder->Add(a, b);
}

Die Include-Verweise und die Lib wurden unter den Einstellungen festgelegt.

UNd hier das Testprojekt:


#include "stdafx.h"
#include "NativeAdder.h"
#include <iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	NativeAdder adder;  //hier kommt es zur Exception
	cout << "Get: " << adder.Add(3,5) << endl;
	char a;
	cin>>a;
	return 0;
}

Ich hoffe mir kann jemand von euch helfen.

Mittlerweile habe ich durch Debuggen rausgefunden, dass es bei folgendem Aufruf passiert mit folgender Debuginformation:

NativeAdder::NativeAdder(void)
{
	_adder = new ILBridgeAdder;
}

-> > Fehlermeldung:

_handle: CXX0030: expression cannot be evaluated

25.01.2011 - 12:17 Uhr

Hallo manullino,

danke für deine Antwort. Ich werde es mir entsprechend anschauen. Scheint denk ich genau mein Problem zu lösen.

20.01.2011 - 12:26 Uhr

Hallo TheGear,

danke für die Info.

Was meinst du genau mit den Begin und End Funktionen?

Die einzigen dieser Art die mir bekannt sind, sind bei der ChannelFactory BeginOpen. Aber da arbeite ich ja mit CreateChannel.

19.01.2011 - 11:20 Uhr

Hallo zusammen,

ich habe ein Problem und habe trotz Google keine Lösung gefunden. Hoffe nun, dass einige von euch mir helfen können.

Es existiert ein WPF-Client, der über einen WCF-Service mit dem Server kommuniziert.

Wenn ich beispielsweise in der GUI einen Service aufrufe wird in der Serviceimplementierung für diese Methode ein Callback ausgeführt.

Bsp: Ich rufe im Client die Methode XYZ auf. In der Methode wird ein Callback gefeuert mit einer Ausgabe "XYZ wurde aufgerufen".
Also: Insert -> Event Inserted

Wenn ich dies in einer Konsolenanwendung laufen lasse wird auch diese Reihenfolge eingehalten.

In der WPF-Anwendung blockiert der Callback jedoch.
Durch Rechereche habe ich rausgefunden, dass man bei der Callback-Implementierung das Attribut "UseSynchronizationContext" auf false setzen muss.
Jedoch wird dann ein asynchroner Aufruf gestartet und mein Callback kommt dann natürlich irgendwann beim Client an und nicht in der von mir im obigen Beispiel beschriebenen Reihenfolge.

Ich will aber die oben genannte Reihenfolge erreichen, ohne dass die GUI blockiert.

Gibt es eine Möglichkeit, die Callbacks synchron aufzurufen ohne mit UseSynchronizationContext = false zu arbeiten?

Danke bereits für eure Hilfe.

15.12.2010 - 08:15 Uhr

In Ordnung, vielen Dank. Dann werde ich die Anforderungen mal weitergeben und schauen was passiert.

14.12.2010 - 19:48 Uhr

Window x:Class="GUI.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:Control="clr-namespace:GUI.Controls"....

**Control **ist dein Alias, dann musst du noch den Namespace (hier: GUI.Controls -> Projekt:GUI -> Ordner:Controls) angeben.

Der Aufruf erfolgt dann etwa so:
<Control:IrgendeinControl>...</Control:IrgendeinControl>

Siehe hierzu auch:
http://msdn.microsoft.com/de-de/library/ms747086.aspx

14.12.2010 - 19:25 Uhr

hm... WPF ist hier absolut fehl am platz. Ihr seit schon unter den minimalanforderungen des .NET Frameworks.....

Das habe ich mir auch schon gedacht. Ich habe jedoch keine direkten Hardware-Anforderungen an WPF bzw. das .NET-Framework gefunden, mit denen ich einen neuen Rechner rechtfertigen könnte. (Wir arbeiten bereits mit dem 4.0-Framework)

@JAck30lena:
Weißt du eventuell einen Link, wo ich die Anforderungen finden kann?
Das mit dem Timer-Intervall hochschrauben hab ich auch schon versucht, hat aber wenig gebracht.

Welche Hardware-Mindestanforderungen würdet ihr mir empfehlen, damit ich für den genannten Fall eine einigermaßen gute Performance erreichen kann?

14.12.2010 - 19:18 Uhr

Grundlegend ist die Darstellung mittels WPF kein Problem. Solange ich die UDP-Komponente nicht einbinde und dadurch das Netz nicht kontinuierlich abgehört wird, habe ich eine Auslastung von maximal 12%. Die Informationen aus dem UDP-Paket (Größe: ca. 1,4 MB) dienen der Animation von Bewegungen. Sobald ein Paket eintrifft, werte ich die Daten aus und rufe die Animation auf dem Control auf. Dann steigt die CPU-Auslastung auf bis zu 80% und schwankt immer wieder (kommt aber nicht unter 50%).

Bei der Auswertung der Daten starte ich die Animation nur, wenn sich die Daten auch nicht geändert haben.

Ich habe also soweit alles optimiert was geht, aber ich sehe keine Möglichkeit mehr, weniger Auslastung zu erreichen.

Ich habe selbst schon zu einem schnelleren Rechner geraten.

14.12.2010 - 18:09 Uhr

Vielen Dank für eure Vorschläge.

Ich habe die Vorschläge nun aufgegriffen und entsprechend in der GUI einen DispatcherTimer alle 100ms laufen. In dem Tick-Event greife ich über die UDP-Schnittstelle auf die aktuellen Daten zu.

Jedoch ergibt sich keine wirkliche Verbesserung der CPU-Auslastung.

Kurz zur weiteren Info:

Der Rechner (Vorgabe durch Firma) hat nur 600 Mhz und Windows XP Embedded. Außerdem wurde die GUI mit WPF erstellt.

Es wird nur ein Paket über UDP versendet. Die Daten werden von einer SPS alle 10 ms versendet mittels Broadcast, d.h. ich bin mit den 100ms schon gut dabei.

Gibt es eventuell noch weitere Ideen? Ich finde einfach keine Optimierung mehr.

14.12.2010 - 11:13 Uhr

Hallo Leute,

ich habe ein kleines Problem und hoffe ihr könnt mir helfen:

In einer eigenen Assembly wird mittels dem UDPClient und der Methode BeginReceive ein asynchrones Lesen eines UDP-Pakets gestartet. Sobald das Paket empfangen wird feuere ich ein Event, für das ich mich in einer anderen Assembly (GUI-Kontext) registriere. Nun muss ich natürlich den Thread wechseln, da ich mich noch in dem Thread der UDP-Assembly befinde und somit nicht auf die UI-Controls zugreifen kann.

Für diesen Wechsel habe ich bereits die Klasse SynchronizationContext bzw. den Dispatcher mit BeginInvoke und Invoke verwendet. Jedoch wird mein Rechner durch diesen Wechsel sehr beansprucht und ich erhalte eine Auslastung von 90%.

Zusätzlich erhalte ich das Receive-Event alle 100 ms, da das Paket alle 10 ms versendet wird und ich im 100 ms-Takt die Daten lese.

Nun meine Frage:
Gibt es eine Möglichkeit den Threadwechsel effizient und performant zu lösen?

Der Code für den UDPClient sieht so aus:



private void RunClient()
{
  if (_udpClient == null)
  {
     _udpClient = new UdpClient((IPEndPoint)_EndPoint) 
                                 {Client = {ReceiveTimeout = 100}};
  }

  var updState = new UdpState {Client = _udpClient, EndPoint = (IPEndPoint)    _EndPoint};
          
   _udpClient.BeginReceive(ReceiveCallback, updState);
}

private void ReceiveCallback(IAsyncResult aAr)
{
   try
  {
      var client = ((UdpState)aAr.AsyncState).Client;
      var endPoint = ((UdpState)aAr.AsyncState).EndPoint;

      var receivedPackage = client.EndReceive(aAr, ref endPoint);

      var socketState = new SocketState(receivedPackage, endPoint, _Port);

      client.BeginReceive(ReceiveCallback, aAr.AsyncState);

      if (DataPackageReceived != null)
     {
         DataPackageReceived(socketState, new NetEventArgs("", "", 0, null));
     }
  }
  catch(Exception exception)
  {
     Trace.WriteLine("Exception on receive action for port: " + exception.Message);
   }
}

Hier die Registrierung in der GUI_Assembly:


...
private NetService _service;
...
private void HandlePackage()
{
  _service.PackageReceived += (sender, e) => SynchronizationContext.Current.Send(delegate { .. });
}

17.09.2010 - 07:52 Uhr

Hallo witte,

danke für den Tipp. Den Link hatte ich schon vorher gesehen, hat mir aber nicht soviel gebracht, da es Linq to Sql war. Hab unter folgender Adresse ein besseres Beispiel gefunden, mit dem ich das Problem lösen konnte.

http://support.microsoft.com/kb/555893/en-us

Das ganze funktioniert analog auch mit dem Sql Server 2008.

In dem Beispiel fehlt lediglich, dass die Connection mit Open() geöffnet wird. Weiterhin muss noch auf dem SqlCommand der ExecuteReader() - Befehl ausgeführt und der zurückgegebene Reader wieder gleich geschlossen werden.

Nochmals danke für die Hilfe. 🙂

16.09.2010 - 12:38 Uhr

verwendetes Datenbanksystem: <SQL Server 2008 Express>

Hallo Leute,

ich habe bereits nach einer Lösung meines Problems im Forum bzw. unter Google gesucht, aber nichts gefunden. Hoffe deshalb, ihr könnt mir weiterhelfen.

Ich verwende derzeit das Entity Framework 4.0. Ich habe eine Tabelle Person mit ID und Name. Wenn nun eine Fremdapplikation eine neue Person in die Datenbank einfügt, möchte ich darüber in meiner Applikation informiert werden.

Ich habe leider keine Erfahrung mit Triggern oder ähnlichem.

Wie kann ich das genau realisieren?

Danke schon mal für eure Hilfe.

01.09.2010 - 14:53 Uhr

verwendetes Datenbanksystem: <Firebird Datenbank>

Hallo zusammen,

ich nutze in unserem Projekt eine Firebird Datenbank und das Entity Framework des .NET 3.5 SP1.

In unserem Projekt gibt es folgende Verbindung:

Menu - 1 ------- 0..* - Parameter

Ich habe also eine Menu und eine Parameter Tabelle in der Datenbank.

Wenn ich einen Parameter mittels Linq to Entities updaten möchte wird beim SaveChanges eine System.Data.UpdateException ausgelöst. Die Fehlermeldung lautet:

"Entitäten in DatabaseContext.Parameter sind an der Beziehung FK_Menu_Parameter beteiligt. 0 Menu wurden gefunden. 1 Menu wird erwartet."

Mein Update-Funktion sieht folgendermaßen aus:


public void UpdateParameter(int parameterID, Parameter updateableParameter, int associatedMenuID)
{
   var existingParameter = (from parameter in Context.Parameter where     parameter.ID == parameterID select parameter).First();

    existingParameter.Text = updateableParameter.Text;
    existingParameter.Menu = (from menu in Context.Menu where menu.ID == associatedMenuID select menu).First();
    Context.SaveChanges();
}

Das Context-Objekt ist eine Singleton-Klasse und beinhaltet die context-Instanz für das Entity Framework.

Beim Debuggen habe ich festgestellt, dass das richtige Menu gefunden wurde und dem parameter-Objekt zugeordnet wird.

Ich verstehe deshalb nicht, warum die Exception auftritt, da dem Parameter-Objekt ein Menu referenziell zugeordnet wurde.

13.07.2010 - 13:09 Uhr

In der Datenbank wird ein Stored Procedure ausgeführt, sobald sich die Daten in der Datenbank ändern.

Der Kontext ist einfach nur der, dass ich informiert werden möchte, wenn sich Daten in der Datenbank ändern. Ich möchte ja nicht alle 5 Sekunden prüfen, ob es neue Daten oder modifizierte Daten gibt. Die Benachrichtigung soll durch Events geschehen.

Über die Firebird .NET API ist es möglich, sich auf bestimmte "Events" dranzuhängen.

Mit "von außen" meine ich andere Clients, die die Datenbank nutzen. Beispielsweise ändert ein Client den Vornamen einer Person und dies möchte ich per Event mitbekommen.

13.07.2010 - 12:33 Uhr

Vielleicht habe ich mich ein wenig unverständlich ausgedrückt.

Das EF hat bereits eine Verbindung zur Datenbank.
Um nun Events von Firebird registrieren zu können, muss zunächst ein Firebird-Connection-Objekt erstellt werden. Dann muss die Verbindung geöffnet werden. Dieses Objekt übergibt man dann einem EventHandler (hier: FbRemoteEvent).

Würde ich das nun auch so machen, hätte ich ja zwei offene Verbindungen zur Datenbank (Die Verbindung des FbConnection-Objekts und die des EF).

Ich habe auch bereits mit den partiellen Methoden OnValueChanged, etc. versucht, auf Änderungen zu reagieren, aber dies funktioniert nicht.

Hatte vielleicht einer von euch bereits dieses Problem oder eventuell einen Workaround?

Leider ist in diesem Projekt Firebird als Datenbank Pflicht.

12.07.2010 - 13:43 Uhr

verwendetes Datenbanksystem: Firebird

Hallo zusammen,

ich rätsel schon eine Weile, wie man Events der Firebird Datenbank mittels Entity Framework registrieren kann.

Ich weiß aus der Firebird-Dokumentation, dass es ein FbRemoteEvent gibt, aber das benötigt ein Connection-Objekt. Ich arbeite aber mit dem EF und nicht direkt mit Connection-, Reader-, etc. Objekten.

Gibt es eine Möglichkeit Events von Firebird mit dem EF zu registrieren?

Beispiel:
Ich habe eine Tabelle Person. Diese Tabelle wird mit dem EF gemappt. Werden nun von außen die Daten der Tabelle Person geändert, wird ein Event von der DB ausgelöst. Auf das Event möchte ich mich in der Klasse Person dranhängen. Ich weiß nur nicht wie ich mich da draufhängen kann.

Weiß einer von euch Rat?