Laden...
J
Jelly myCSharp.de - Member
Burden (Luxemburg) Dabei seit 09.09.2007 1.114 Beiträge
Benutzerbeschreibung

Forenbeiträge von Jelly Ingesamt 1.114 Beiträge

16.08.2010 - 19:01 Uhr

Ich geh ganz von der Idee weg, dass der Client überhaupt mit Datenbankobjekten in Berührung kommt, egal welcher Art (DataSet, Array). In meinen WCF Services biete ich nur die Methoden an, die für die Client wichtig sind. Soll z.B. eine Liste von neuen Mitarbeitern her, die seit einem Stichdatum eingestellt wurden, so würdest du, wenn ich dich recht verstehe, eine Methode anbieten, in der der Client den passenden SQL Select dazu formuliert, an den WCF schickt, und eine Array oder ähnliches zurückerhält.

Das halte ich persönlich für nicht gut. Stattdessen würde ich dem WCF Service Contract eine Methode List<Personal> RezentesPersonal (DateTime stichdatum) offrieren.

Das Ganze hat natürlich erstmal den Nachteil, dass diese Methode im Server erstellt werden muss, und den Client bekannt gemacht werden muss. Aber sicherheitstechnich hast du so viel bessere Möglichkeiten, deine Abfragen vor Unfug zu schützen. Zu den Personaldaten gehören beispielsweise auch sein Gehalt, und das sollte aber wohl nur in den seltensten Fällen, und nur unter der entsprechenden Berechtigung, zum Client gelangen. Kann der Client sein Select aber selbst formulieren, wird eine Überprüfung darauf sehr schwierig bis unmöglich.

Datenbankobjekte lassen sich darüberhinaus auch nur bestenfalls Spaltenweise schützen durch entsprechende Logins und Roles, jedoch nicht Datensatzweise. Besteht z.B. eine Anforderung, dass Personaldaten von der Führungsebene in keinem Fall ermittelt werden können, stehst du auch so vor dem Problem, dass sowas auf Datenbankebene allein nur sehr schwer zu realisieren wäre.

Deshalb mein Tipp: immer nur aussagekräftige Methodennamen nutzen können, die dem Client sein Ergebnis direkt liefert. Clients sollten von der DB Architektur niemals in Berührung kommen müssen.

16.08.2010 - 14:00 Uhr

Auf MSI basierende Setups lassen sich eigentlich immer über den Parameter /quiet komplett im Hintergrund installieren. Dabei werden aber lediglich die Standardoptionen gewählt, sprich, es ist z.B. nicht möglich den Installationspfad während der Installation anzupassen.

MSI Setups lassen sich allerdings relativ leicht mittels dem Orca MSI Editor anpassen, so dass speziellen Parameter somit trotzdem per default gesetzt werden können. Es ist in der Praxis tatsächlich meistens so, dass in Firmennetztwerken die Installationspakete so angepasst werden müssen.

Aber dein Projektvorhaben klingt sehr interessant. Ich hab mir auch schon einige Gedanken über eine solche Softwareverteilung gemacht. Ich kam aber noch nicht dazu, es umzusetzen. Lediglich die Architektur hab ich definiert.

Hast du schon ein paar Details, wie du das Ganze umsetzen willst, bzw. handelt es sich überhaupt um ein Projekt das später auch von anderen Usern genutzt werden kann.

26.07.2010 - 16:36 Uhr

Statt nur einen String einzufügen, nutze die TreeNode Klasse, und hinterlege dein Objekt dort in der Tag-Property.

TreeNode tn = new TreeNode("Buch");
tn.Tag = meinBuch;
root.Nodes.Add(tn);
23.07.2010 - 15:13 Uhr

Folgendes sollte funktionieren (anhand von A und B nur):

public abstract class BaseClass
{
    public BaseClass()
    {
        if (!(this is A) && !(this is B))
            throw new Exception("Inheritance is invalid");
    }
}

public abstract class A : BaseClass
{
}

public abstract class B : BaseClass
{
}

public class ConcreteA : A
{
}



public class MoreConcreteA : ConcreteA
{
    public MoreConcreteA(int i)
    {
    }
}


public class InvalidBase : BaseClass
{
    public InvalidBase(string bubu)
    {
    }
}

Klasse ConcreteA und MoreConcreteA können erstellt werden. Instazieren von InvalidBase schmeisst eine Exception.

23.07.2010 - 08:36 Uhr

So, dann weißt du jetzt auch, warum es die Diskussion gegeben hat, die du zuerst nicht verstanden hast. 😃 Weil es keinen eindeutig richtigen oder falschen Weg zur Lösung des Problems gab, sondern eben einen konstruktiven Streit um den richtigen Weg. Das soviele Mitglieder, so beharrlich für den Weg entsprechend der MS Richtlinie plädiert haben, zeigt aber, dass zumindest diese Richtlinie von Microsofts wohl doch mit der vorherrschenden Meinung konform geht.

Sorry, aber ich muss trotzdem nochmal nachhaken.

Ich habe auch in mein Startmenu geschaut, und mal geprüft, welche Programme denn einen direkt Uninstall im Startmenü anbieten. Dabei fällt natürlich erstmal auf, dass die bei keinem MS Programm der Fall. Aber andere namhafte Hersteller von Software bieten dies sehr wohl an... Hier nur mal einige: Google Picasa, Gimp, DevExpress Enterprise, HP Druckertreiber uvm.

Ich denke also, dass es ebenso berechtigt ist, die sogenannte Richtlinie von MS sehr wohl in Frage zu stellen, wenn es doch andere grosse Softwarehersteller ebenso tun.

Letztlich streitet man hier also über persönliche Vorlieben, was besser oder schlechter ist. Damit kann ich leben, und ich finde solche Diskussionen ja auch sehr hilfreich. Persönlich war mir z.B. nichts von solch einer MS Richtlinie bekannt. Zumindest weiss ich jetzt, dass es eine solche gibt. Aber in der ganzen Diskussion ging es halt eben, wie bereits oben erwähnt, ausschliesslich um diese Richtlinien, und es wurde kollektiv die Meinung verbreitet, dass man sich bitte an diese Richtlinien zu halten hat, und es deshalb eben einfach bleiben lass soll, den Startmenueintrag zu erstellen. Das ist, finde ich, in keinster Weise eine hilfreiche Antwort auf die ursprüngliche Frage. Es darf durchaus erwähnt werden, ja, genau wie meine Darstellung. Aber ich habe den Eindruck, dass stur nur dieser MS Richtlinie lemmingartig hinterhergeiefert wird. Das finde ich eben nicht ok.

22.07.2010 - 19:06 Uhr

wenn jemand etwas tun möchte, dass gegen Entwicklungsrichtlinien verstößt, wäre es fahrlässig, ihn nicht darauf hinzuweisen.

Richtig. Dagegen hab ich ja auch nix gesagt. Nur wurde bis dato ausschliesslich in diese Richtung diskutiert, und die eigentliche Frage ging komplett verloren.

Außerdem ist es immer gut über den Tellerand zu gucken und nicht nur stur zu beantworten, was gefragt ist.

Ich habe über die andere Tellerrandseite gekuckt (die Erde ist doch eine Scheibe), und wollte zum Ausdruck bringen, dass es nicht immer Microsofts Richtlinien sind, die eine alleinherrschende Meinung vertreten muss, sondern es durchaus auch andere Meinungen und Argumente gibt.

22.07.2010 - 16:00 Uhr

Habe soeben das hier gefunden und getestet. Funktioniert einwandfrei, und ist sauberer als eine Batchlösung, da bei einem Programmupdate der ProductCode in der Regel mitändert. Das würde bedeuten, die bat-Datei immer mit neu anzupassen.

22.07.2010 - 15:39 Uhr

Ich versteh nicht ganz warum hier nur was von MS Richtlinien und ähnlichem diskutiert wird. Die Frage ist, wie ich über einen Shortcut ein Programm wieder deinstallieren kann, und nicht, was MS empfielt und was dann dadurch scheinbar besser sein soll.

Zurück zum Thema:
Man kann die msiexec mit Commandlineparametern aufrufen, die es einem erlauben, auch eine Software wieder zu deinstallieren (sogar Silent wenn man möchte). Das Einzige, was man dazu braucht, ist der ProductCode, der ja im Setupprojekt unter Visual Studio angegeben ist. Dieser ProductCode identifieziert eindeutig die Software, und die lässt sich somit über den Uninstall Parameter beim msiexec.exe Aufruf deinstallieren. Die Syntax sollte lauten:

msiexec /uninstall {5361C1F7-CE84-4792-8B90-658AED967C6A}

Es reicht also im eigentlichen Setup einen Startmenüeintrag mit obigen Befehl zu erstellen.

21.07.2010 - 15:18 Uhr

Ich hoste nicht im IIS, aber muss man dort nicht für die Site angeben, dass überhaupt mal eine Authentifizierung genutzt werden soll. Normal sind die Verbindungen zum IIS anonym.

21.07.2010 - 11:51 Uhr

Habt ihr das auch bei normal geschlossenen Verbindungen? ("gekappt" interpretier ich jetzt mal als "unterbrochen") Und trotz "SqlDependency.Stop()"?

Bei einem sauberen Stop() gabs bei mir bislang keine Probleme. Aber wenn der Prozess abschmiert (oder abgeschossen wird), kommt es zum Logüberlauf.

21.07.2010 - 08:10 Uhr

Aber ich will auch Szenarien abfangen wo ein Client für 10 Sekunden kein Netzwerk hat und 3 Notifizierungen nicht bekommt (bzw. rebootet). D.h. das klassische SOA Problem

Wie greifen denn deine Clients auf die Datenbank zurück. Falls direkt, kannst du z.B. bei MSSQL ab VErsion 2005 die SqlDependency Klassen im Framework nutzen. Ist aber fehleranfällig, weil die Resourcen bei gekappten Verbindungen im Server nicht sauber freigegeben werden und sich die Logfiles innerhalbe kürzester Zeit volllaufen (bei uns war es mal 100GB innerhalb von 20 Stunden).

Wenn du bevorzugterweise über eine Middelware gehst, so kann der Middlewareserver doch bei Änderungen eine Notification an all seine Clients schicken, sie sollen doch bitte ihre Daten am Schirm aktualisieren. Bei WCF z.B. wird dies direkt über CallbackContracts erleichtert.

Was ich nicht machen würde: Jede Änderung an die Clients weiterreichen (z.B. ein Feurwehrauto fährt raus, dann würd ich nicht an alle Clients melden, bitte update genau diesen Umstand, sondern ich würde einfach nur eine Benachrichtigung rausjagen, DASS sich was geändert hat. Die Clients ihrerseits machen dann ein komplettes Refresh ihres Displays.

12.07.2010 - 09:37 Uhr

Ich erzeuge mit die Connections jetzt halt dynamisch.

Was sowieso dank Connection Pooling angebracht ist. Globale Connections irgendwo in einer Klasse zu halten gehört nicht zu den "Best Practices" in .NET

12.07.2010 - 08:53 Uhr

Das halte ich für kompliziert und vor allem unperformant. Ich machs normal so:

select DATEADD(dd, 0, DATEDIFF(dd, 0, MyDateTimeValueField))
09.07.2010 - 08:23 Uhr

Ein Prozess auf dem Server überprüft alle angemeldeten User, ob diese noch reagieren.

Wie prüfst du das denn. Der Client kann ja noch z.B. reagieren (Ping), jedoch ist lediglich seine Anwendung abgestürzt. Und diese hat er unter Umständen wieder selbst gestartet, bevor die 3 Minuten verstrichen waren. Der Server denkt also, alles wäre in Ordnung?

Meine Vorgehensweise ist in den meisten Fällen eine ganz andere (branchenbedingt): Ich ändere nichts, sondern ich versioniere nur. Ich mache also kaum Updates in den Datentabellen, sondern füge stattdessen nur hinzu. Somit behalte ich die gesamte Historie.

08.07.2010 - 09:14 Uhr

Jetzt ist erstmal TdF Zeit 👍
(Und der wird selbstverständlich von Andy Schleck gewonnen 8)){gray}

08.07.2010 - 08:12 Uhr

Wie sieht denn die Klasse aus, die dein IClientFunctions Interface implementiert.

06.07.2010 - 07:51 Uhr

Warum machst du das gern im Speicher und unter C#? Ich bezweifele, dass du da jemals an die Performance einer Datenbank rankommst, denn genau dafür sind diese ja konzipert!

06.07.2010 - 07:47 Uhr

Noch was zum Thema Datenhaltung: In gewissen Bereich geht das sicherlich sogar noch weiter. Dann müssen sogar über sämtliche Änderungen an den Daten eine komplette Historie gehalten werden, mit Vermerk des Datums, wann die Änderung durchgeführt wurde, und von wem.

In anderen Bereichen wiederum ist auch im professionellen Umfeld eine Datenhaltung nicht notwendig oder sogar nicht rechtlich. Man denke z.B. an die Kommunikatîonsdaten der Telekomkunden (siehe hier).

Auch für Daten die den Geschäftsprozess nicht betreffen, ist man ebenfalls nicht verpflichtet, alle Daten zu halten, sondern dürfen ruhig bei Bedarf direkt gelöscht werden.

05.07.2010 - 16:07 Uhr

selbst Sachen, die nicht 100%ig wasserdicht sind, können trotzdem praktikabel genug sein. 😃

Da stimm ich dir zu. Es ist alles eine Sache, wie das Problem formuliert wird. Und da die Ausgangsfrage hiess, wie ich erzwingen kann, dass eine Property gesetzt ist, hab ich meine Antwort daraufhin formuliert.

05.07.2010 - 09:28 Uhr

Natürlich... kopfauftastaturhau.

Aber ein

obj.Dispose();

würde Probleme bereiten.

05.07.2010 - 09:00 Uhr

Ich muss bei der Eingabe der Daten die Prüfung schon machen

Sicherlich richtig, aber damit löst du noch nicht alle Probleme. Was ist mit folgendem.

MyClass obj = new MyClass();
myContainer.Something = obj;
obj = null;

Du kannst also sicherlich in Setter von Something prüfen, ob dein value != null ist. Aber ein anschliessenden setzen auf Null deiner Ursprungsreferenz kriegst du so nicht verhindert.

05.07.2010 - 08:49 Uhr

Festplatten kosten nix.

Fiberchannel Speicherplatz schon, und zwar jede Menge. (1300€ für 70GB ohne Raid)

Löschen macht man nicht.

Wenn das so pauschal richtig wäre, gäbe es wohl kaum den "delete" Befehl.

Man archiviert nur. Als Firma muss man 5-10 Jahre lang Digitale Daten aufbewahren.

Und danach löschen?

Ausserdem ist ja auch nicht jeder in einer Firmenanwendung unterwegs.

Imho helfen deine Aussagen also überhaupt nicht weiter sondern im Gegenteil, sind einfach nur subjektive pauschale Aussagen ohne Nutzen für andere.

@jegetro: Zu deiner Frage:
Cascading Delete geht in dem Fall nicht. Alternativ kannst du aber in einem BeforeDelete Trigger auf deiner SW Tabelle einstellen, dass der entsprechende Einträg in der Job Tabelle zuerst gelöscht wird.

02.07.2010 - 11:49 Uhr

Deine GetRunningJobList Methode dient ja nur dazu, dem Client diese Liste zu präsentieren. Du machst es dir denkbar schwer, mit diesen Callback Aufrufen, da du sie in diesem denke ich wirklich nicht brauchst. Die void GetRunningJobList() Methode würde ich so definieren:

[OperationContract]   // Kein IsOneWay hier
List<JobDb> GetRunningJobList();

public List<JobDb> GetRunningJobList();
{
    List<JobDb> tmplist = new  List<JobDb>();

    foreach (JobStructure.Job job in JobListRunning)
    {
        if (job.Status == "Running" || job.Status == "Queued")
           tmplist.Add(job.Convert());
    }
    return tmpList;

Aus Clientsicht ist nix anderes notwendig, als ein einfacher host.GetRunningJobList-Aufruf, und er kriegt als Ergebnis seine Liste. Du umgehst die Callbacks, du brauchst dir keine Sorgen um Synchronisation machen, und machst im Code weiter, sobald der Client seine Liste hat.

Sollte die Operation lange dauern (bei momentaner Implementierung sicherlich nicth der Fall), kannst du Clientseitig den Aufruf auch in einem separatem Thread starten. Aber Callbacks brauchst du hier nicht.

02.07.2010 - 09:26 Uhr

reicht es beim letzteren einfach das Programm zu starten und die Adresse zum Datenbankserver anzugeben. Allerdings ist das dann auch der höchste Aufwand.

Dafür gibt es auch Tools. Eins wäre der SQL Packager von Redgate. Hab aber selbst noch nicht damit gearbeitet.

02.07.2010 - 09:22 Uhr

Du verwirrst mich. Du schreibst einerseits:

Der Server läuft, der Port ist offen, er arbeitet auch noch die Jobs ab, aber ich krieg keine Callback response mehr vom Dienst zum Client.

und andererseits:

Client schickt CreateJob an Dienst, Dienst sendet nur kurz einen string "job created" + sessionid. Verbindung wird geschlossen.

Genauso wie beim Status abholen. Client schickt GetStatus, Server sendet eine List<>. Verbindung wird geschlossen.

Wenn letzteres stimmt, dann brauchst du nach meinem Verständnis doch keinen Callback Kanal, sondern du gibst das Ergebnis (dein Statusstring bzw. deine List<>) einfach als Rückgabewert zurück.

Wie beendest du denn die Verbindung? Clientseitig?

02.07.2010 - 08:47 Uhr

Das stinkt nach Timeouts... Wenn der Server über einen definierten Zeitraum nix mehr von seinem Client hört, würgt er dessen Verbindung ab.

Probier doch mal client seitig z.B. alle 2 Minuten eine Dummy Methode Ping() am Server aufzurufen, die nix macht. Dadurch wird der Server nochmals angesupst und signaliert ihm, dass der Client immer noch besteht.

01.07.2010 - 23:02 Uhr

Ich bräuchte eigentlich nur ein Tool, welches sämtliche Statements der DB-Instanz mitloggt und den jeweiligen usern zuordnet.

Bei der Express Version fehlt vielleicht ein solches Tool, aber bei der Develop Edition ist es ziemlich sicher bereits bei der SQL Installation dabei, und nennt sich SQL Profiler. Das Tool sollte eigentlich bei allen Problemen an der DB die Anlaufstelle Nummer eins sein, wenn man nich auf andere kostspieligere Tools zurückgreifen will.

01.07.2010 - 12:37 Uhr

Zur Zeit geht 80% meiner Freizeit für Sport drauf. Das liegt aber momentan auch daran, daß mir am 18. Juli ein Ironman bevor steht. Danach geh ich dann das Ganze wieder gelassener an. Aber Sport ist und bleibt mir einfach unheimlich wichtig.

Vor 2 Jahren habe ich eine Zeit lang fast keinen Sport betrieben. Ab und zu alle 14 Tage mal bischen Rad. Ich fühlte mich fett, unbeweglich, unwohl. Es fehlte mir einfach der Pepp zu allem. Ich kann allen nur raten, sich ausgiebig zu bewegen, der gesamte Körper und sein Gemüt wird sich dafür danken.

01.07.2010 - 12:09 Uhr

Das wird so nicht gehen. Zum Serialisieren brauchts du Schreibrechte auf die Eigenschaften. Ebenso wird ein parameterlose Konstruktor benötigt.

30.06.2010 - 11:49 Uhr

Einen Value-Type kann man auch null setzen:

Int32? i = null;
28.06.2010 - 14:24 Uhr

Ich hatte nun gestern etwas Zeit, das updateSystem daheim zu testen. Also eins schon mal vorweg: Es hat tadellos funktioniert, ohne Fehlermeldungen, und ich muss wirklich sagen, dass dir das Ganze echt gut gelungen ist.

Ein Anmerkung dennoch:

Es gibt leider keine Möglichkeit, einen Prozess nach dem Update wieder erneut zu starten, und dabei die ursprünglichen Commandline Parameter wieder mitzugeben. Soll heissen: Ich starte mein Anwendung mit

app.exe /x

Beim Start meiner Anwendung prüfe ich dann auf Updates, und führe diese dann gegebenfalls durch, und möcht anschliessend wieder meine app.exe aufrufen. Der Aufruf an sich ist ja kein Problem, aber der Parameter /x geht mir verloren.

28.06.2010 - 10:26 Uhr

Fehlentscheidungen gehören zum Fußball dazu und machen einen Teil seines Reizes aus!

Wenn du die Wettskandale als Teil seines Reizes mit einbeziehst, dann geb ich dir Recht. 🤔

21.06.2010 - 14:40 Uhr

es ist so, daß eine Aktivierung der Volltextsuche, den Kunden pC erstmal lahmlegen würde, da die nachträgliche Volltextsuchenaktivierung die "riesig" gewordenen Tabellen erstmal über Indizes fragmentiert soweit ich weis). Die Tabellen werden nachträglich also mit Indizes versehen.

Wie willst du denn bitte Performance erreichen, wenn du noch nicht einmal Indizes erstellt hast. Ohne Index wird bei jedem Select ein "Full Table Scan" vom SQL Server durchgeführt, und das kostet bei 1,5 Mio. Records nunmal Zeit.

21.06.2010 - 14:04 Uhr

Hast du denn die Volltextsuche aktiviert, oder suchst du mit dem Like Operator '%ulle%' ?

21.06.2010 - 11:17 Uhr

Ich halte die Chefs als Hindernisse für Unit Tests für ein hausgemachtes Problem der Entwickler. Wenn ein Chef mir reinreden würde und sagte, ich solle mal die Klassen so und so schneiden, würd ich ihm da folgen? Wenn ein Chef mir reinreden würde und sagte, ich solle mal besser EF statt NHibernate benutzen, würd ich ihm da folgen?

In beiden fällen lautet die Antwort nein. Chefs haben das nicht zu entscheiden.

Falsch, denn dafür sind Chefs da: um Entscheidungen zu fällen.

Wenn einem das nicht passt, dann hat man entweder im Vorstellungsgespräch nicht herausgefunden, dass die Firmenpolitik vielleicht nicht gerade zu einem passt, oder man hat im Nachhinein die Möglichkeit, den Arbeitsplatz zu wechseln und sich einen anderen Chef zu wählen.

Aber nur über das Managment zu lamentieren is unsinnig.

21.06.2010 - 07:39 Uhr

Das ist ja eben der Vorteil, wenn Server und Client sich eine Contract DLL teilen, anstatt den Proxy über "Add Service Reference" automatisch zu erzeugen.

Es spricht nix dagegen, z.B. das INotifyPropertyChanged Interface im DataContract zu implementieren, um so den Client auf etwaige Änderungen zu benachrichtigen. Das läuft aber dann natürlich clientseitig ab, und der Client muss sich dann gegebenfalls natürlich darum kümmern, die Änderungen dann auch wieder mit einer geeigneten Methode des ServiceContracts dem Server mitzuteilen.

20.06.2010 - 10:54 Uhr

Verwende ich dann fuer den DataContract Employee auch ein Interface?

Nein. Zumindest ist mir nicht bekannt, dass man Interfaces als Datacontracts nutzen kann. Sowohl Server, als auch Client müssen den DataContract mit seinen DataMembers kennen.

Du hast dazu prinzupiell 2 Möglichkeiten:

  1. Server und Clients verweisen auf eine DLL, die all deine Data- und ServiceContracts enthält. Deine Clients nutzen auch diese DLL, und haben somit alles, was sie brauchen um mit dem WCF Server zu kommunizieren.
  2. Du startest deinen Server, und läasst die Clients automatisch die Service und Contracts Klassen erstellen (Add Service Reference im VS).

Persönlich tendiere ich zu 1, da es mehr Möglichkeiten bietet. So kannst du z.B. weitere Properties in die DataContracts ablegen, z.B.:


public string FullName
{
    get { return FirstName + " " + LastName; }
}

Aber weiterhin darauf achten, dass deine DataContracts nicht wieder Methoden wie Save() oder Load() enthalten. Das ist Aufgabe des WCF Servers.

Und wie verwende implementierst du auf der Client-Seite so etwas wie Dirty-Flag?

Was verstehst du unter einem Dirty-Flag?

18.06.2010 - 07:56 Uhr

@Manullino... Wann bist du denn aufgestanden 😃

Ich glaube, du vermischst gerade Service orientiertes Denken mit Objektorientierung. Das ist ein Fehler, der oft begangen wird, wenn man das erste mal mit WCF oder ähnlichen Technologien in Berührung kommt.

In WCF werden lediglich DataContracts zwischen Server und Clients ausgetauscht. In dem Wort steckt eigentlich schon alles drin: es geht um Daten. Und in einem solchen DataContract haben Methoden generell nix verloren, jedenfall kein Save oder LoadById.

Die Methoden gehören in den ServiceContract, also die Schnittstelle zwischen Server und Client. Der ServiceContract implementiert ein Interface, das in der ServiceKlasse implementiert wird, und das der Client auch kennt. Und genau hier gehört deine Save und LoadById Methode rein. Natürlich mit anderen Parametern, etwa:


bool SaveEmployee (Employee emp);
Employee LoadEmployeeById(Int32 id);

Die Employee ist dein DataContract, das natürlich sowohl Server und Client kennen müssen. Deshalb empfielt es sich, bei einer WCF Architektur, das Ganze in 3 Assemblies zu unterteilen:

  1. Deine Contracts, also sowohl ServiceContract als auch all deine DataContracts
  2. Dem Server, der eine Referenz auf die Contracts braucht
  3. Dem Client, mit ebenfalls einer Referenzt auf die Contracts, aber natürlich NICHT auf den Server.
17.06.2010 - 13:32 Uhr

SandcastleGUI kapselt das Ganze eigentlich recht schön in einem Gui.

17.06.2010 - 13:30 Uhr

Ich versuche immer, am Anfang von neuen Projekten, alle Abläufe mit den Verantwortlichen zu klären. Z.Z. arbeite ich z.B. an einem erweiterten Lagersystem. Hierbei versuche ich dann, alle hausinternen Abläufe soweit wie möglich klar zu strukturieren. z.B. soll bei bestimmten Bestellungen immer ein Ausdruck an gewissen Arbeitspläten erfolgen. Ein Prozessablauf muss eben immer ganz klar strukturiert sein, und genau definiert sein, wie in welchen Situation agiert werden soll. Ein klassischer Workflow halt. In meinem BL werden die einzelnen Schritte des Workflows als Methoden implementiert. Da gibt es dann, um im Bsp. zu bleiben, Methoden die heissen OrderSomething, SendReportToClient etc. Um diese Methoden aufzurufen, bedarf es natürlich definierten Rechten. Es kann also nicht jeder einfach mal so die OrderSomething Methode aufrufen, ohne dazu befugt zu sein. Aber wenn er es darf, gibt die Methode einen Wert zurück, der wieder als Input oder Bedingung in das nächste Element meines Workflow einfliesst.

Der gesamte Workflow an sich wird ebenfalls nochmals in einer Methode im WCF Server gekapselt. Das sollte eigentlich der einzige Aufruf vom Clienten sein.

So, lange Rede kurzer Sinn. Der Client muss nur die InputStrukturen für dern Workflowaufruf kennen, und dessen Rückgabewerte. Was intern im Server abläuft, muss den Client ja nicht interessieren. Er braucht tatsächlich lediglich die Strukturen zu kennen, die ihn interessieren, und halt anzeigen können.

Ich bin der Meinung, dass man so Sachen nur schwer automatisieren kann, und deswegen halte ich auch nicht sonderlich viel von irgendwelchen Vorlagen. Ich modelier mir das Ganze dann lieber selber zusammen, und zeichne meine Workflows mit Bleistift auf Papier.

16.06.2010 - 07:42 Uhr

Alles hinter einen WCF zu packen find ich persönlich eine tolle Vorgehensweise. Ich habe nun einige Projekte hinter mir, bei denen ich sowohl die BL und dan DAL als WCF hab laufen. Der Client kriegt nur die BL zu sehen, und die BL greift auf die DAL zu. Ich finde das wunderschön gekapselt, und der Client kriegt serverseitig eben nur die Rechte, die er braucht.

Mein DAL bau ich mir immer selbst, und verzichte meist auf irgendwelche Tool wie NHibernate und co. Nun ja, das ist sicherlich Geschmackssache. Wenn ich das händich mach, hab ich den Eindruck, besser modelieren zu können. Das liegt aber primär auch wohl nur daran, dass ich mich mit NHibernate oder dem Analogon aus dem DevExpress Paket (eXpress Persistent Objects) noch nie so richtig beschäftigt habe. Schlecht sind die Tools aber sicherlich nicht.

15.06.2010 - 13:20 Uhr

Kannst du noch vom Kauf zurücktreten. Gesetzlich ist da doch was von 14 Tagen, oder?

14.06.2010 - 10:41 Uhr

Fussball ist ein Spiel, und kein Sport. Und aus dem Spielealter bin ich raus 😃

Persönlich begeister ich mich nicht für die WM, bei mir ist es meine Frau daheim die jedes Spiel kucken will. Soweit ist sie gekommen, die Emanzipation 😃

Aber sagen wir's mal so. Ab dem Viertelfinale werd ich mir sicherlich trotzdem gerne das eine oder andere Spiel reinziehen. s

11.06.2010 - 11:07 Uhr

Da du MSSQL benutzt, kannst du Cascading Delete auf dem Foreign Key aktivieren. Dadurch werden durch Löschen eines Rezeptes automatische alle Detail Records in der zweiten Tabelle mit gelöscht. Es ist also Vorsicht hier geboten. Normalerweise benutzt man nämlich gerade Foreign Keys, um ein Löschen eines Rezeptes zu unterbinden, wenn noch DetailRecords exitieren, eben um zu verhindern dass diese ins Nirvana zeigen.

11.06.2010 - 10:14 Uhr

Was Khalid sicherlich meint, ist dass du nicht über den Namen des Rezeptes referenzieren sollst. Der Name gehört in die Rezept Tabelle. Neben dem Namen gehört hier ein Primary Key rein, z.B. eine fortlaufende Nummer. Die Id SOLL KEINE Information enthalten. Sie soll nur dazu dienen, dein Rezept intern zu identifizieren.

Deine einzelnen Rezeptschritte gehören korrekterweise in eine getrennte Tabelle. Und dies Tabelle brauch dann eine Spalte RezeptId, die auf dein Rezept referenziert.

Somit hast du keine Probleme, dein Rezeptname zu updaten. Du musst lediglich den entsprechenden Record über den Primary Key updaten.

Da deine fortlaufende Id keine Information trägt, wirst du diese auch nie updaten müssen. Deshalb soll die Id keine Info tragen, da es ansonsten immer mal passieren kann, dass der Inhalt ändern kann. In jede Tabelle gehört ein solcher Primary Key. Ob das eine fortlaufende Nummer ist, oder eine Guid, ist Geschmackssache und anwendungsspezifisch.

11.06.2010 - 07:56 Uhr

sollte sie auch der eigentliche Empfänger bekommen.

Eben... sollte. Wirklich überprüufbar ist das nicht.

Wenn es also darum geht, Daten zuverlässig an Externe weiterzureichen, ist ein EMail Versand nicht die bevorzugte Technologie.

09.06.2010 - 08:48 Uhr

Nein, das ist nicht möglich. Datenhaltung in DataRow und DataTabls sind nicht an eine Connection gebunden. Die Quelle der Daten muss ja auch nicht zwangsläufig eine Datenbank sein. Lediglich ein DataAdapter wird herangezogen, um die Daten in die clientseitige DataTable zu schaufeln. Der DataTable selbst ist es daher egal, von woher die Daten kommen.

09.06.2010 - 08:06 Uhr

Fullack, Herbivore. Besser kann man's nicht formulieren. 👍

07.06.2010 - 10:30 Uhr

Mehr fällt mir hierzu echt nichts ein X(

klick

04.06.2010 - 11:23 Uhr

v Ein direktes synchronisieren der Datenbanken geht nicht

Heisst das sie hängen nicht in einem Netzwerk?

Falls doch, nutze den Data Export des SQL Servers. Ansonsten kannst du auch ein Backup der gesamten DB ziehen, und auf Rechner B wieder in einer temp Datenbank aufspielen, und dein Data Export von dort aus erledigen.