Laden...
Avatar #avatar-3273.gif
Mr. Bart Simpson myCSharp.de - Member
Anwendungsentwickler Mittelfranken Dabei seit 13.03.2004 502 Beiträge
Benutzerbeschreibung

Forenbeiträge von Mr. Bart Simpson Ingesamt 502 Beiträge

27.08.2014 - 11:43 Uhr

...was ich dabei schon desöfteren als riesigen "Zeitfresser" identifizieren konnte ist das Logging der SQL Statements (z.B. auf die Konsole oder ins Ausgabefenster von VS).

Bart Simpson

27.08.2014 - 11:41 Uhr

Hi,

letztendlich werden durch deinen Code Instanzen der Klasse System.Net.Mail.Attachment erzeugt. Diese müssen wieder via Dispose aufgeräumt werden, damit die Handles freigeben werden. Wenn ich mich recht entsinne genügt es dafür aber auch die eigentlich MailMessage via Dispose freizugeben.

Bart Simpson

18.06.2014 - 10:51 Uhr

ändert sich das Design der DB denn grundlegend von Mandant zu Mandant, oder ist es fest und es kommen nur hier und da neue Spalten hinzu? Es gibt zwar zumeist durchaus Gemeinsamkeiten zwischen den Mandanten – aber es geht deutlich über ein paar neue Spalten hinaus.
es gab eine Metadata-Datenbank mit den Tabellen und Spalteninformationen …was ja nun informationstechnisch nichts anders ist wie mein Vorschlag mit den Mapping-Attributen in der Datenklasse
Aber das Ganze klingt für mich eher nach NoSQL. Wie schon erwähnt – theoretisch ja, aber die anderen Anforderungen (die hier „out of scope“ sein sollen) sprechen dagegen.
Wenn du es dynamisch haben willst, aber als ORM kommt eigentlich etwas wie Simple.Data in Frage. Klingt interessant – muss ich mir mal ansehen.
…kurioserweise wird genau das mein nächstes Blogthema werden… Na da bin ich dann aber mal gespannt 😃
Damit das Mapping funktioniert - passend zum Code Kommentar - muss die Klasse selbst wissen, wie das Mapping funktioniert Das ist ja nun auch nicht wirklich viel anders als mein Vorschlag mit den Mapping-Attributen – Du umgehst damit natürlich die „Auflösung“ (Reflection), aber rein von der gewonnenen Information aus betrachtet hast Du dort auch nicht mehr. Oder überseh ich da was?

Bart Simpson

18.06.2014 - 10:05 Uhr

Mandant-System heisst im einfachsten Fall nur, dass jeder Mandant eine eigene DB hat … Ein bisschen mehr heißt das bei mir schon 😉 Aber das ist nicht das Thema.
Ich verstehe zugegebenermaßen nicht alles; ist aber auch keine triviale Anforderung. Das ist mir durchaus bewusst – ich hab nur versucht, den für die Fragestellung relevanten Kern zu beschreiben. Das ist einerseits natürlich sinnvoll, nimmt Dir (und den anderen potentiellen Beantwortern) aber natürlich ein wenig den Kontext.
wobei ich das so nie tun würde Warum? Hast Du da gute Gründe (was ich mal aus Deinen üblichen Antworten hier im Forum schlussfolgere) oder ist das eher ein Bauchgefühl, evtl. resultierend aus der dürftigen Fragestellung?
Probleme seh ich zB beim automatischen Mapping ohne Metadata ("dumm sein") Ganz sooo dumm muss es ja nicht sein – sowas wie Attribute, die für’s Mapping relevante Informationen transportieren ist durchaus denkbar. Was mir vorschwebt ist in etwa ein „Komplexitätslevel“ wie es z.B. bei WCF Datenklassen üblich ist, so á la :

 [MapToTable("Table")]
        public class DataClass1
        {
            [MapToColum("Col1")]
            public string MyStringProperty { get; set; }

            [MapToColum("Col2")]
            public int MyInt32Property { get; set; }
        }

Das ist zeitgleich auch das Haupt-Problem aller bestehenden, derzeit verfügbaren ORM im .NET Umfeld Es ist mir durchaus bewusst, dass Reflection schnarchlangsam ist. Aber dafür gäbe es für meinen konkreten Anwendungsfall durchaus „Vermeidungsstrategien“ – z.B. könnte der DB-Layer beim ersten Aufruf physische Assemblies generieren (z.B. mit Roslyn) und diese anschließend nutzen. Das ist zwar sicher nicht die perfekte Lösung, aber wäre zumindest deutlich schneller – und wäre auch kein wirkliches Problem, da (wie schon erwähnt) das DB-Schema irgendwie dennoch unveränderlich ist, wenn es einmal erstellt wurde.
Im Prinzip hast Du auch nur ein Pluginsystem; und wie man Pluginsysteme modular an eine DB anbindet: dafür gibt es ja hunderte Vorschläge. Funktioniert soweit ja auch (siehe zB Wordpress, DotNetNuke; die verwendet ja genau so ein Verhalten - aber eben über passende Schnittstellen). Da hab ich wieder ein klares Jain…
Im Kern hast Du recht – aber es gibt einen wesentlichen Unterschied. Systeme wie die genannten haben zwar evtl. mit unterschiedlichen Schemas (=DB-Server-Software, MSSQL vs. MySQL etc.) zu tun, die durchzureichenden Daten sind aber im Prinzip gleich (ich vermute mal es sind letztlich irgendwelche Interfaces, die an das entsprechende DB-Plugin übergeben werden).
In meinem Szenario ist es aber so, dass z.B. an DB1 Daten aus Klasse1, Klasse2 und Klasse3 übergeben werden – an DB2 jedoch (völlig anders strukturierte) Daten aus Klasse 4 und Klasse5.

Bart Simpson

18.06.2014 - 09:23 Uhr

Die Anforderung, dass Du kein festes Schema hast, schließt eigentlich jede relationale Datenbank aus; das ist Dir bewusst?

Da antworte ich mal mit einem klaren Jain 😁
Das Schema ist zwar nicht wirklich fest (im Sinne von "zur Designzeit des DB-Layers") - aber "später" dann doch unveränderlich. Will sagen, es gibt z.B. für einen Mandanten eine DB, deren Schema (nach initialer Entwicklung) feststeht. Nur weiß eben der DB-Layer davon nix und muss entsprechend flexibel sein...

Ich hoffe die Erklärung beschreibt, was ich meine - eine bessere Erklärung fällt mir grad nicht ein (zumindest nicht, wenn ich keinen Roman schreibe...)

Aber ich gebe Dir natürlich recht - ein relationales DB-Schema ist für die Anforderung natürlich erst mal "suboptimal". Aber die restlichen (in meinem Post nicht genannten) Anforderungen an die "Mandanten-DB" schreien geradezu danach.

Bart Simpson

18.06.2014 - 08:39 Uhr

Hallo,

ich arbeite derzeit am Backend eines Projekts und bin auf der Suche nach Ideen für den DB-Layer. Evtl. hat hier ja jemand eine gute Idee 😁
Was ich entwerfen möchte ist im Prinzip eine Art O/R-Mapper – allerdings mit ein paar speziellen Anforderungen – aber der Reihe nach:

  • Es geht um verschiedenste Objekte, die gespeichert und wieder geladen werden sollen (Backend: SQL-Server ≥2008R2)
  • Die Objekte an sich können (noch) frei gestaltet werden, d.h. es wäre z.B. möglich eine gemeinsame Basisklasse einzuführen – das würde ich aber gerne vermeiden, da die Datenklassen möglichst „dumm“ (und von daher einfach zu entwerfen) bleiben sollen.
  • Es müssen 1:n oder m:n Beziehungen darstellbar sein – auch über (max.) drei Ebenen hinweg.
  • Das Ganze soll dynamisch (also zur Laufzeit) passieren, da das Gesamtsystem aus einer feststehenden Basis (z.B. der DB-Layer) und einem Plugin-Baukasten (z.B. die Datenklassen) bestehen soll und somit der DB-Layer zur Entwurfszeit nichts davon weiß, was er eigentlich „durchschleusen“ muss.
  • Das Gesamtsystem muss im Prinzip Mandantenfähig sein – allerdings gehen hierbei die Anforderungen soweit, dass die Mandanten theoretisch physisch trennbar sein müssen (sprich: anderer Server)

Vereinfacht gesagt, bekommt der DB-Layer „irgendein“ (ihm -im Sinne des Typs- unbekanntes) Objekt und das soll er jetzt in eine (dynamisch zu bestimmende) DB speichern. Von der DB soll der DB-Layer auch möglichst wenig wissen, es wäre aber möglich eine Art „Brückenkopf“ (also einen feststehenden, immer vorhandenen Teil) darin zu integrieren.
Ein erster (sehr einfach umzusetzender) Lösungsvorschlag wäre nun z.B. die Datenklassen serialisierbar zu gestalten (DataContract o.ä.) und dann in XML-Spalten in der DB zu speichern. Das würde universell und unabhängig vom konkreten Datentyp funktionieren – aber dadurch werden natürlich Datenbankseitige Abfragen im Vergleich zur Speicherung in „normalen“ Tabellen (bzw. deren Spalten) wesentlich komplexer (die SQL-Abfragemöglichkeiten für XML-Datenspalten sind meiner Meinung nach ein Graus – aber das ist ein anderes Thema :evil: )
„Schöner“ wäre es in meinen Augen, wenn die Objekte in irgendeiner Form analysiert würden und die Properties auf Tabellenspalten gemappt würden. Das sollte vom Grundprinzip her auch nicht sonderlich schwer umzusetzen sein (z.B. via Reflection) – allerdings wird’s sehr schnell blutig… Man denke nur an die oben erwähnten 1:n oder m:n Beziehungen.
Ich hab bisher noch keinen tieferen Blick auf O/R-Mapper wie NHibernate, Linq2SQL oder Entity Framework werfen können. Kennt jemand die Lösungsstrategien, die dort angewandt werden? Da sollten doch zumindest ähnliche Konzepte drinstecken – wenn auch evtl. mit Code-Generatoren gelöst. Aber selbst das wäre ja für mein Problem denkbar (Reflection.Emit oder auch Roslyn). Was mich allerdings abschreckt ist, dass das ja für sich genommen größere Projekte mit einer dementsprechenden Entwicklungshistorie sind – also nichts, was man mal eben so in einem Projekt nachbaut…

Irgendwelche Ideen?

Bart Simpson

17.06.2014 - 17:17 Uhr

So aus dem Bauch raus sag ich mal, Du solltest in Deiner for-Schleife prüfen, ob der UInt16-Wert > 0 ist - und nur dann an den String anhängen...

Zumindest schließe ich das aus dem Code, den mir der WMI-CodeCreator erzeugt 😉 Der ist immer wieder einen Tipp wert...WMI-Code Creator

26.05.2014 - 22:43 Uhr

Wie schon erwähnt wurde, kannst Du das im Prinzip alles selber machen - mit den Bordmitteln von .net...

Zwei Anmerkungen dazu meinerseits:
a) Das Darstellen eines Images in einem für Enduser benutzbaren UI ist eine Aufgabe, die sich durchaus bewältigen lässt - allerdings hat man das nicht mal eben schnell runtergecodet. Von daher stellt sich die Frage, ob der Aufwand lohnt, oder ob man sich auf dem Markt eine fertige Komponente dafür sucht (wie z.B. GdPicture.NET).
Es geht aber definitv alles mit Bordmitteln - auch bei Multi-Page Tifs. Stichwort Bitmap.SelectActiveFrame.

b) Wenn man das selbst entwickelt, sollte man auch wissen, dass das .net Framework nicht alles unterstützt was Tiff so kann. Z.B. ist kein Decoder für die JPEG-Kompression innerhalb des Tifs vorhanden. Da musst Du dann zu sowas wie dem schon erwähnten LibTiff greifen.

Bart Simpson

22.04.2014 - 10:05 Uhr

Diesen Fehler bekomme ich jetzt:

Fehlermeldung:
Beim Aufruf einer COM-Komponente wurde ein HRESULT E_FAIL-Fehler zurückgegeben

Das Problem hatte ich (in leicht abgewandelter Form) auch schon - bei mir lag's schlicht und ergreifend daran, dass der Adobe Reader erst einmal "manuell" gestartet werden musste, damit man die EULA abnickt - erst danach ist das COM Objekt nutzbar...

Bart Simpson

22.01.2014 - 11:15 Uhr

ExecuteScalar liefert dir auch ein Int zurück.
Deshalb kann es eigentlich nicht klappen.

Also soweit ich das in der Doku sehe gibt ExecuteScalar nicht int sondern object zurück - ich kenn mich bei SQLite nun nicht wirklich aus, aber bei allen anderen DB-Systemen, die ich kenne, ist das so, dass in dem zurückgegebenen object das Ergebnis der ersten Spalte aus der ersten Zeile zurückkommt. Man muss es nur noch richtig casten.

D.h. wenn Stunde ein int ist, wird auch sum(Stunde) int werden und somit int zurückkommen. Hat Stunde aber einen anderen Typ, wird auch was anderes bei ExecuteScalar zurückkommen (wenn auch wieder gecastet als object).

Bart Simpson

13.01.2014 - 11:19 Uhr

Yep, das gibt es, siehe hier:
>

Genau sowas hab ich gesucht! 😁

Bleibt noch die Frage: Wie sieht's bei Libre- / Open-Office aus?

Bart Simpson

13.01.2014 - 11:14 Uhr

Ich verwende Office 2010 - und natürlich Visible = false.

Dass das Probleme machen kann und weder empfohlen noch supported wird, wissen wir ja schon - ich würd's aber gern trotzdem machen... :evil:

13.01.2014 - 10:57 Uhr

Naja, darüber zu diskutieren macht ja keinen Sinn, weil Word nicht mit einem Service funktioniert.
Auch nicht mit Visible = False; es braucht einen GUI Handle; egal ob da nun ein Nutzer aktiv dran ist oder eine Anwendung. Auf Deutsch: nur wenn jemand am System angemeldet ist und auch die GUI angezeigt werden kann.

Die Aussage irritiert mich nun doch ein wenig... Ich habe aktuell einen kleinen Prototyp als Dienst laufen, welcher genau das tut. Da ist niemand angemeldet und es gibt auch keine Handles für die GUI. Trotzdem tut Word klaglos seinen Dienst...

Dass es z.B. wenn Word eine Msgbox anzeigen will zu Problemen kommt ist mir durchaus bewusst - aber grundsätzlich geht das erst mal schon. Von daher finde ich die Aussage "... weil Word nicht mit einem Service funktioniert..." schon ein wenig auf dünnem Eis.

Bart Simpson

13.01.2014 - 10:44 Uhr

Und wie öffnest Du Word ohne UI?

Ok... ich hätt's vielleicht anders formulieren sollen. Was ich meinte ist, dass die Funktionalität, die ich nutzen will keine Interaktion mit dem Benutzer voraussetzt und deshalb auch kein UI angezeigt werden müsste (Visible=false).
Das bedeutet natürlich nicht, dass ich nicht trotzdem im Hintergrund einen Word-Prozess starten würde - es würde nur eben das UI nicht angezeigt (...was bei Diensten eh nicht ginge...)

Worum's mir ging, ist also (auch) die Frage "wie zickig ist Word / OpenOffice in so einem Anwendungsfall". Und: Wo sind die Ecken und Kanten bzw. wie umgehe ich diese?

Bart Simpson

13.01.2014 - 10:33 Uhr

Ein Service kann keine Oberfläche öffnen; Word (auch Open Office) benötigt aber eine Oberfläche, damit es funktioniert.

Das ist mir durchaus bewusst - die von mir in Betracht gezogenen Funktionen benötigen jedoch (eigentlich) kein UI...

(Vereinfachtes) Beispiel: Word.doc öffnen -> Text als Header einfügen -> Speichern als PDF

Bart Simpson

13.01.2014 - 10:20 Uhr

Hallo zusammen,

ich versuche grad einen Hintergrundprozess (wird wahrscheinlich ein Dienst, könnte aber evtl. auch im IIS gehostet werden) zu erstellen, der u.a. ein paar Funktionen haben soll, welche sich perfekt mit Office Automatisierung lösen liesen (z.B. hätte Word alle nötigen Funktionen an Bord und ließe sich via PIAs super anbinden).

Nun ist aber laut MS (und auch den FAQs hier im Forum) Office (bzw. im speziellen Word) nicht dafür gedacht, im Hintergrund zu laufen und es kann immer wieder zu unvorhersehbaren Problemen kommen (was ich auch schon leidlich am eignen Leib erfahren musste - aber man muss es natürlich ausprobiert haben... :evil: )

Frage 1: Gibt's hierzu irgendwelche Best Practices, oder ist es ein totales No-Go, Word im Hintergrund zu benutzen?

Frage2: Wie sieht's an der Stelle mit Libre- bzw. Open-Office aus? Theoretisch ist das ja (via Uno oder wie das heißt..) ebenfalls automatisierbar. Gelten dort die selben Grundsätze zur Hintergrundverarbeitung?

Bart Simpson

09.12.2013 - 17:20 Uhr

Da fällt mir spontan jetzt nur eines ein: Strange!

Der geneigte Leser fragt sich nun*Warum gibt der DataContractSerializer dann ein in XML ungültiges "Zeichen" eigentlich aus? ?( *Was muss man sich vorstellen, was da bei der Standardisierung des XML abgelaufen ist? Wenn ich schon per #x... Notation ein Escaping mache, dann erlaube ich es bei den "niedrigen ASCII-Werten" nur für #x9, #xA und #xD??? WTF? 🤔 🤔 🤔

Gibt's trotzdem 'nen Workaround? Oder muss ich jetzt noch ein Base-64 Encoding o.ä. drumherum machen? Das wollt ich eigentlich nicht, da sonst erst mal nichts mehr direkt lesbar ist (außer ich mach im Code eine Weiche für das eventuelle Auftreten eines nicht erlaubten Zeichens...)

Bart Simpson

09.12.2013 - 10:08 Uhr

Verwendetes Framework: .net 4.0

So weit ich über XML und die darin möglichen Escape-Mechanismen informiert bin, sollte das ASCII-Zeichen 0x03 doch eigentlich in XML problemlos mittels des Literals  escaped werden können. Dummerweise musste ich aber feststellen, dass die XElement-Klasse weder beim Parsen noch beim Erzeugen damit umgehen kann:

XElement xml1 = new XElement("Test");
xml1.Value = "Value" + (char)0x03;
string s1 = xml1.ToString();
 string s2 = "<Test>Value&#x3;</Test>";
XElement xml2 = XElement.Parse(s2); 

Beide Codefragmente werfen eine Exception, dass das hexadezimale Zeichen mit dem Wert 0x03 ein ungültiges Zeichen wäre. Meiner Meinung nach sollte das aber eigentlich nicht so sein, da korrekt escaped wurde...

Liege ich hier falsch, was die XML-Spezifikation angeht, oder macht hier das .net-Framework einen Fehler?
Kennt jemand einen Weg, das Problem zu umgehen?

Witziges Detail am Rande: Die DataContractSerializer-Klasse erzeugt im Zusammenspiel mit dem XmlTextWriter für string-Properties mit dem Text genau das von mir erwartete XML - nur kann eben XElement nicht damit umgehen... 🤔
Ich hab mal eine kleine Extension-Method zur Illustration gebaut:


public static XElement ToXElement(this object objectToSerialize)
        {
            if (objectToSerialize == null)
            {
                return null;
            }
            else
            {
                string rootName = objectToSerialize.GetType().Name;
                DataContractSerializer ser = new DataContractSerializer(objectToSerialize.GetType(), rootName, ContractNamespacePrefix + objectToSerialize.GetType().Namespace);
                using (StringWriter w = new StringWriter(System.Globalization.CultureInfo.InvariantCulture))
                {
                    XmlTextWriter writer = new XmlTextWriter(w);
                    ser.WriteObject(writer, objectToSerialize);
                    return XElement.Parse(w.ToString());
                }
            }
        }

 [DataContract]
    public class Test
    {
        [DataMember]
        public string A { get; set; }
        
     }

Test t = new Test()
            {
                A = "Test " + (char)0x03,
            };


            var data = t.ToXElement();


Die Routine erzeugt (meiner Meinung nach korrekterweise) das XML im XmlWriter, jedoch raucht das return-Statement ab... 😜

Mr. Bart Simpson

20.03.2013 - 15:58 Uhr

Sorry, wenn ich diesen alten Thread nochmal aufwärme, aber das hier

du hast recht, das ist ganz schön versteckt wie du ein PDF-File öffnest und daraus ein Graphics-Objekt bekommst aber das hier sollte dir weiterhelfen:

>

und das hier

Googel spuckt bei der Suche nach pdfsharp gleich die offizielle Seite
>
aus. Dort gibt's ein Sampel das u.A. PDF's als Bild speichern kann.


>

hat mich schon erstaunt... Das wäre Eurer Beschreibung nach genau etwas was ich im Moment suche - aber: soweit ich das sehen kann geht es damit eben genau nicht, (als Datei) existierende PDFs in Images zu wandeln. Man kann in "gerade in Erzeugung befindlichen" rummalen - das war's aber auch. Oder belehrt mich jemand (evtl. mit einem Codefragment) eines besseren?

Bart Simpson

03.03.2013 - 11:09 Uhr

Erst mal vielen Dank für die Einschätzungen / Meinungen und Tipps!

Ich versuch mal auf Eure Anmerkungen einzugehen:

@herbivore:
Die Bedenken mit dem recht hohen Aufwand habe ich auch, deswegen hatte ich dies ja eingangs auch als eine der Kernfragen formuliert.
Bei der Nutzung der Windows-eigenen Dialoge muss ich Dir aber widersprechen. Wenn ich den Codeproject Artikel (von dem ich oben schon einen anderen Teil erwähnte) richtig interpretiere, sollte das durchaus möglich sein. Denn dort wird genau das gemacht. Wenn auch die zu bearbeitende Information (also der Security Descriptor) in dem Beispiel trotzdem aus dem Dateisystem stammt, so zeigt es doch die prinzipielle Machbarkeit. Und auch der von Coder007 erwähnte Artikel lässt mich daran glauben.

@herbivore & Coder007:
Die Problematik des Umgehens wenn man Zugriff auf die Rohdaten hat ist mir bewusst, stellt aber in meinem Szenario kein wirkliches Problem dar. Die (Gesamt-) Applikation soll als Client-Server-Architektur realisiert werden, so dass man vom nutzenden Client aus das Ganze nicht einfach umgehen kann. Der Fall dass jemand Zugriff auf den Server hat ist für mich daher erst mal "out of Scope".

@Coder007:
Den MSDN Artikel hatte ich noch nicht gesehen (wie erwähnt, ich hab erst begonnen mich da einzulesen), aber das sieht echt vielversprechend aus.
Mein Hauptproblem ist vermutlich eine Kombination aus zwei Faktoren:
a) Das bis dato nur vorhandene "Halbwissen", dass ich mir bis jetzt aneignen konnte.
Dazu noch: Meintest Du z.B. dieses Buch?
b) Ich entwickle nunmehr seit mehr 10 Jahren (.net 1.0 Beta 2) de facto nur noch für's .net Framework (wenn man mal von PInvoke und ein paar Delphi Projekten absieht) - und in C/C++ war ich damals noch nicht auf einem Level um solche Dinge umzusetzen. D.h. ich hab auch noch eine gewisse "Sprachbarriere", da viele der Beispiele / Libraries hier nun mal nicht in C# sind X(
Aber da ich mich sowieso wieder mehr in die C++ Richtung mit Nativen Anwendungen orientieren wollte, ist das vielleicht gar nicht so schlecht... 8)

Dennoch: Wenn jemand weitere Infos oder gar Libraries/Codeschnippsel kennt, ich würde mich freuen!

Bart Simpson

02.03.2013 - 18:56 Uhr

Die Seite über die Securable Objects kannte ich schon - und mir ist auch bewusst, was es bedeutet (hoff ich jedenfalls 😄) - ich hab mich nur in meinem Beitrag auf die NTFS-Schiene beschränkt, um's nicht noch weiter aufzublähen...

Zum Thema: Ich les da genau das raus, was ich geschrieben hat. Nämlich dass ich eigenen Objekten einen Security Descriptor verpassen kann. Und da es den in zwei Ausprägungen gibt und eine davon (Selbstreferenzierend glaub ich heisst's in der Übersetzung) komplett als Speichblock vorliegt / vorliegen muss, dachte ich es sollte möglich sein, genau diesen als BLOB in die DB zu schreiben und dann wieder auszulesen...

Aber ich bin für weitere Infos sehr dankbar...

Bart Simpson

02.03.2013 - 12:51 Uhr

Hallo zusammen,

ich plane derzeit eine Applikation (bzw. ein Subsystem davon) welches vereinfacht gesagt einen Baum mit angehängten Sicherheitsinformationen darstellt. Für ein besseres Verständnis des grundsätzlichen Ansatzes stellt man sich am besten das NTFS Dateisystem mit seinen Ordnern, Dateien und natürlich den darin ebenfalls abgebildeten Sicherheitseinstellungen (Access Control Lists, ACL) vor.
Meine „Objekte“ sind allerdings keine Dateien und Ordner sondern Knoten und Blätter eines in einer DB abgebildeten Baumes. Nun möchte ich beim Zugriff eines Users auf z.B. einen Knoten prüfen, ob der User überhaupt die nötigen Rechte besitzt (also wieder ganz ähnlich zum NTFS-Modell, wo der User z.B. das Recht zum Durchsuchen eines Ordners besitzen muss). Das Ganze soll (ebenfalls wie NTFS) mit Vererbung bzw. dem „Durchbrechen“ selbiger funktionieren – also im Prinzip völlig frei konfigurierbar sein.

Nun ist es ja so, dass die eigentliche Sicherheitsprüfung kein Feature von NTFS ist, sondern vom „darüber liegenden“ Betriebssystem, also Windows. ( Kleiner Exkurs: Wer’s nicht glaubt, darf gern mal mit einer Linux-Live-CD seinen Windows-Rechner booten und sehen, wie einfach der Zugriff auf Ordner ist, die im NTFS eigentlich für den User nicht zugänglich sein sollten.)
Das heißt, Windows liest beim Zugriff auf z.B. einen Ordner die ACLs aus und entscheidet anhand des aktuellen Users (genauer: des Tokens, das dem aktuellen Prozess zugeordnet ist) ob der Zugriff erteilt oder verweigert wird. Hierfür muss der sog. Security Descriptor des NTFS-Objekts gelesen und entsprechend ausgewertet werden. Genau hier möchte ich mich quasi „einklinken“: Warum sollte ich eine komplette (noch dazu hochkomplexe) Verwaltung der Sicherheitsinformationen selbst implementieren, wenn doch die gesamte Infrastruktur schon vorhanden ist und auch genutzt werden kann? Anstelle des Security Descriptor eines NTFS-Objekts möchte ich daher meine eigenen Objekte mit Security Descriptoren versehen und alles weitere analog zum Dateisystem handhaben. Konkret stelle ich mir vor den jeweiligen Security Descriptor als BLOB in der DB mit abzulegen und dem Knoten zuzuordnen. Die „Serialisierbarkeit (wie man es innerhalb von .net wohl nennen würde) des Security Descriptors ist dabei natürlich eine Grundvoraussetzung.
Ich habe mich schon etwas in das Thema eingelesen. V.a. die Artikel in der MSDN z.B. Access Control List Editing in .NET bzw. Windows-Sicherheitsfunktionen für eigene Anwendungen nutzen) und auf Codeproject (The Windows Access Control Model: Part 2: Do I Have Access?) lassen mich vermuten, dass das Ganze an sich möglich wäre.
Für mich stellen sich jetzt zwei Hauptfragen – und ich hoffe es gibt hier im Forum Leute, die sich in diesen Tiefen von Windows auskennen:
Ist das grundsätzlich so machbar? Ich bin mir nämlich nicht absolut sicher, dass ich alle Infos rund um das Thema auch wirklich richtig interpretiere.
Wenn es grundsätzlich möglich ist, ist der Weg sinnvoll? Und mit sinnvoll meine ich a) von der Idee her (sprich: Ist es evtl. aus irgendwelchen Gründen eine wirklich dämliche Idee?) und natürlich b) vom Aufwand her (sprich: Ist das im Rahmen eines Projekts in sinnvoller Zeit umsetzbar?)

Sollte es hier im Forum zufällig jemanden geben der Erfahrungen im Bereich von „Private Object Security“ hat, wäre ich natürlich dankbar für einen Erfahrungsaustausch. Interessant für mich sind natürlich auch konkrete Code-Fragmente (C# ist natürlich bevorzugt), Libraries oder weiterführende Literatur / Artikel.

Bart Simpson

10.02.2013 - 11:51 Uhr

Ich würde auch zu der Variante mit "Applikation erzeugt GUID und gibt sie an DB weiter" tendieren. Wobei ich bei sowas oft auch einen Mittelweg wähle: Eine SP erzeugt eine GUID, führt dann das INSERT Statement aus und gibt (u.a.) die GUID zurück.

Worüber man sich normalerweise keinerlei Gedanken machen muss, ist die Kollision - und das gilt auch bei einer sehr großen Menge an Daten! Wenn die Systemeigenen Routinen verwendet werden um die GUID zu erzeugen, dann ist das iirc immer ein GUID v4 - und wer sich dabei Gedanken über die Kollisionswahrscheinlichkeit Gedanken macht, der sollte mal darüber nachdenken, ob nicht innerhalb der nächsten 30 Sekunden ein Asteroid auf die Erde stürzt der die komplette Menschheit auslöscht... 😁
Nur so als Tip: Bei Stackexchange.com wird's ganz gut erklärt und Wolfram Alpha liefert die Visualisierung... Bei 10^17 GUIDs liegt die Wahrscheinlichkeit immer noch bei ~ 0,xxx Promille. Das sollte für die meisten praktischen Anwendungfälle genügen 8)

Bart Simpson

29.01.2013 - 16:49 Uhr

Hallo herbivore,

ich geb Dir völlig Recht - das Prozedere aus dem von Dir verlinkten Thread sollte bei solchen Problemen immer abgeklappert werden...
Dummerweise hab ich das aber (meiner Meinung nach) schon quasi komplett hinter mir. Kam vielleicht im original Post nicht so ganz raus, war aber mit "...kann ich nicht reproduzieren..." gemeint.

Das Problem mit der im anderen Thread verlinkten Vorgehensweise ist, dass ich den Weg des "alles unnötige aus dem Projekt rauswerfen" nicht so weit gehen kann wie ich müsste / wollte, da sonst die für die App nötige Infrastruktur nicht mehr funktioniert. Also bleibt v.a. der Weg mit der kleinen, neu aufgebauten TestApp. Und da ich mich an der konkreten Stelle nur auf Properties aus der Config beziehe sollte das (meiner Meinung nach) eigentlich auch reichen.
Wie schon geschrieben tut's das aber eben leider nicht (die Mini-Testapp zeigt das "Fehlverhalten" nicht) und das obwohl im Debugger alles gleich ist (Variableninhalte, etc.).

Was ich mittlerweile noch rausgefunden habe: Es scheint irgendwie so zu laufen, dass die Bedingung im Ausdruck geprüft wird (denn es wird der Getter aus der generierten Config-Klasse im Debugger erreicht und dieser liefert auch den korrekten Wert zurück) - aber das Setzen der Zielvariable wird "einfach nicht ausgeführt"... Und das macht mich jetzt doch etwas ratlos 🤔

Bart Simpson

29.01.2013 - 14:33 Uhr

Hallo zusammen,

ich bin grad während des Debuggings auf etwas ziemlich merkwürdiges gestossen - kennt irgendwer das Phänomen bzw. dessen Ursache?

Zur Umgebung: .net 4.0 Konsolen-Applikation mit Debug-Build, erstellt mit VS 2010 Ultimate SP1.

Die Applikation hat über die Einstellungen (also letzendlich app.config) zwei Werte definiert (siehe oberer Teil des Bildes im Anhang). Diese möchte ich dann letztendlich nutzen und habe dafür (u.a.) folgendes Statement drin:

Guid? pluginFilter = Properties.Settings.Default.LoadDebugPlugin ? Properties.Settings.Default.DebugPluginId : (Guid?)null;

Die Zeile wird im Debugger erreicht und die Werte können abgefragt werden (siehe Überwachungsfensterausschnitt im Anhang).

Wenn ich die Zeile nun ausführen lassen, ist pluginFilter immer null - und das trotz der Tatsache, dass das LoadDebugPlugin-Flag auf true steht...

Witzigerweise kann ich das Ganze nicht reproduzieren, denn wenn ich eine kleine Testapp entwerfe, die die Stelle nachbildet funktionierts plötzlich.
Wenn ich den ?-Operator rausnehme und stattdesssen folgenden Code reinnehme

pluginFilter = null;
            if (Properties.Settings.Default.LoadDebugPlugin)
            {
                pluginFilter = Properties.Settings.Default.DebugPluginId;
            }

funktionierts auch... aber warum zum ?$%§ klappt's nicht mit dem ursprünglichen Code? Ich hatte schon den Verdacht, dass der Debugger irgendwelche "alten" Binaries verwendet, aber ein Klick auf "Projektmappe bereinigen" brachte auch nichts.

21.01.2013 - 14:39 Uhr

Also ohne es jetzt wirklich geprüft zu haben bin ich mir doch zu 99% sicher, dass es nicht möglich ist, den SQL-Server arbeiten zu lassen, ohne ein Programm mit einer offenen Verbindung zu haben.
D.h. Du kannst das Ganze zwar evtl. in einen Hintergrund-Thread verlagern o.ä., aber wenn Du wirklich den Prozess beendest, bricht der SQL Server die Ausführung ab.

Spontan fällt mir genau ein Ausweg dazu ein: Nutze den SQL-Server Agent oder auch ein eigenes, separat anzustossendes Programm, welches (im Hintergrund) läuft und die Verbindung aufrecht erhält. Das Ganze wird dann aus Deinem Hauptprogramm heraus nur "angestossen" und läuft quasi losgelöst (und v.a. als eingener Prozess) - egal ob nun DeineApp.exe oder der Agent.

Bart Simpson

16.11.2012 - 15:59 Uhr

Ja, ich hab die Routine schon ausprobiert...
Allerdings muss ich zugeben, dass ich nicht sicher bin ob meine Probleme wirklich daher kommen, oder ober die mit dem Handle aufgerufene API einfach nur Probleme macht.
Dummerweise steh ich da jetzt vor einer Art Henne-Ei-Problem... Wie soll ich rauskriegen, ob's an der API liegt oder am DIB? Oder gibt's eine Möglichkeit das DIB irgendwie zu "validieren" (wobei das natürlich für das Handle gelten müsste, ein erzeugtes File wäre IMHO nur "zweitklassig" zur Prüfung geeignet).

Bart Simpson

16.11.2012 - 14:34 Uhr

Ich weiß, der Thread ist schon ziemlich alt, aber hast Du da eine funktionierende Lösung hinbekommen?

Ich steh grad vor dem Problem aus einem Bitmap-Objekt ein DIB zu erzeugen, welches ich dann als Handle an eine API weitergeben muss (ich brauch also ein hDIB)...
Aber ich steh grad irgendwie auf'm Schlauch 🤔

Bart Simpson

13.09.2012 - 09:59 Uhr

Hallo zusammen,

mich würde mal interessieren, was Ihr so für Tools einsetzt um Dokumentationen, Konzepte o.ä. zu schreiben.

Was ich damit **nicht **meine: Alles was (von der Idee her) in Richtung Sandcastle nDoc o.ä. geht - also Tools um z.B. aus dem Quellcode (bzw. den Kommentaren) eine Doku bzw. deren Grundgerüst zu erstellen.

Was ich meine:
Ich versuch's mal an 'nem Szenario zu erläutern... Wir haben bei uns Vorgaben hinsichtlich Coporate Identity, d.h. Dokumente sollen "ähnlich" aussehen. Wenn wir nun an einem (Kunden-)Projekt arbeiten, entwerfen wir dafür z.B. ein Konzeptpapier, dass die fachlichen Anforderungen erläutert. Dabei handelt es sich im wesentlichen um viel Prosa (um nicht zu sagen "BlaBla") angereichert mit ein paar Bildern strukturiert in Kapitel und kleinen Gimmicks wie einem Inhaltsverzeichnis oder einer (im Prinzip ähnlich funktionierenden) Liste für z.B. noch offene Punkte.

Dafür prädestiniert scheint auf den ersten Blick natürlich Word (oder evtl. vergleichbares). Allerdings treibt mich das regelmässig in den Wahnsinn 😜
Word hat da nämlich nicht nur eine, sondern diverse Macken, die einem das Leben oft schwer machen - v.a. wenn mehrere Leute an so einem Dokument arbeiten wobei sich u.U. einige nicht an die bei Word im Hintergrund werkelnden Konzepte wie z.B. Formatvorlagen halten und z.B. einfach Schriftgrößen manuell ändern um das Layout zu bekommen, dass sie gern hätten...

Ich hab nun schon experimentiert, Word soweit zu beschneiden (ja das geht, fragt aber nicht, was das für ein Aufwand ist...), Formatierungen nur noch über die Formatvorlagen zuzulassen. Trotzdem halte ich es immer noch für eine Sträflingsarbeit und Word macht _regelmäßig _extremste zicken, die _ich _in keinster Weise nachvollziehen kann 🙄

Ich hab nun schon mit dem Gedanken gespielt auf Latex zu setzen, aber da (wie schon erwähnt) auch "technisch weniger versierte" Leute daran arbeiten können sollen, scheidet das wohl leider aus, denn selbst WYSIWYG-nahe Editoren sind dafür IMHO nicht zu gebrauchen...

Von daher die Frage: Was nutzt Ihr hier so? Gibt's da überhaupt was vernünftiges?

Gespannt auf Eure Antworten und Vorschläge,
Bart Simpson

29.08.2012 - 11:17 Uhr

Nur so als Tip: Da gibt's schon eine nette Library dafür in den Codesamples von Microsoft: All-In-One Code Framework

Bart Simpson

24.07.2012 - 14:10 Uhr

Also mittlerweile hab ich noch ein paar Dinge dazu gefunden...
*Mit einem eigenen UriParser sollte es möglich sein *Evtl. reicht es auch schon, das richtige Flag auszuschalten: http://stackoverflow.com/questions/856885/httpwebrequest-to-url-with-dot-at-the-end *Die obsolete Konstruktor-Überladung für die Uri-Klasse ist laut Doku explizit deaktiviert und gibt immer false weiter

24.07.2012 - 13:35 Uhr

Wenn ich das richtig verstehe, ist das Problem, dass die WebRequest Klasse letztlich keinen String sondern eine Uri-Instanz nutzt. Und genau diese lässt es irgendwie nicht zu, die Url so zusammen zu bauen, wie es benötigt würde...

 string _websiteUrl = "http://www.web.de/";
            string url = Uri.EscapeDataString(_websiteUrl);
            Uri tgt = new Uri("https://www.x.com/webmasters/tools/feeds/" + url);

Das ergibt für url: http%3A%2F%2Fwww.web.de%2F
Aber in tgt steht: https://www.x.com/webmasters/tools/feeds/http://www.web.de/

11.06.2012 - 10:02 Uhr

Nur als Ergänzung: Das Laden von nativen DLLs lässt sich auch mit einem anderen Ansatz lösen - ohne setzen von Path-Variablen etc.
Folgende Vorgehensweise ist dafür nötig:

a) Native Windows Calls einbinden


[DllImport("Kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadLibraryEx(string dllFilePath, IntPtr hReservedNull, LoadLibraryFlags dwFlags);

[DllImport("Kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool FreeLibrary(IntPtr hModule);

[DllImport("Kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

b) den Pfad zur richtigen Dll bestimmen (ggf. abhängig von Environment.Is64BitProcess)
c) die DLL laden und den Zeiger darauf merken

 LoadLibraryEx("FullPathToLibrary.dll", IntPtr.Zero, LoadLibraryFlags.LOAD_WITH_ALTERED_SEARCH_PATH)

d) Für jede benötigte Funktion jeweils den Einsprungpunkt holen und einen entsprechenden Delegate darauf erezugen lassen

private static TDelegate GetFunctionDelegate<TDelegate>(IntPtr dllHandle, string functionName)
           where TDelegate : class
        {
            IntPtr function = NativeCalls.GetProcAddress(dllHandle, functionName);
            var funcPointer = Marshal.GetDelegateForFunctionPointer(function, typeof(TDelegate));
            return funcPointer as TDelegate;
        }

TDelegate muss dafür definiert sein als Delegate mit der Signatur der zu importierenden Funktion.
Am Ende kann die DLL dann auch noch mit FreeLibrary wieder freigegeben werden.

Vorteile hiervon: *Es wird alles dynamisch geladen *Der Pfad zur DLL kann frei angegeben werden (ohne PATH-Variable und andere Unwägbarkeiten) *Der Zeitpunkt des Ladens (und Entladens) der DLL kann exakt bestimmt werden *Es ist (wenn nötig) möglich die aufzurufenden Methoden dynamisch zu bestimmen (Zugriff via String, der den Namen enthält) *Verschiedene Funktionen mit gleicher Signatur können über den selben Delegate-Typ importiert werden (keine mehrfachen Importe via DllImport-Attribut nötig)

Nachteil: Mann muss einiges "von Hand lösen" - z.B. via Marshal.GetLastWin32Error() immer die nativen Calls überprüfen und das Ergebnis ggf. in eine ".net-konforme" Exception packen, was beim "normalen" DllImport schon automatisch mit dabei ist.

Bart Simpson

08.06.2012 - 11:21 Uhr

Hallo,

ich schlage mich gerade mit der Anbindung einer nativen Library herum. im wesentlichen hab ich das gelöst, allerdings frage ich mich gerade wie Exception-Handling bei meiner Problemstellung aussehen sollte / muss...

Szenario: Ich binde eine native (C++) Dll via P/Invoke ein. Allerdings nicht direkt via [DllImport]-Attribut, sondern ich lade die DLL mittels LoadLibraryEx und hole mir dann die Proc-Adressen als Delegate (GetProcAddress im Zusammenspiel mit Marshal.GetDelegateForFunctionPointer). (Hintergrund hierfür ist, dass ich so dynamisch den Pfad zur DLL angeben kann und z.B. zwischen x86 und x64 wechseln kann.)
Eine Klasse, die die Ganzen nativen Calls kapselt und bei Dispose alles (inkl. FreeLibrary) wieder sauber aufräumt dient hierbei als zentraler Anlaufpunkt. Diese Wrapperklasse lasse ich nun nicht in meiner normalen Appdoman laufen, sondern nur in einer eigenen, dafür erzeugten Appdomain. Alle Aufrufe dahin werden durch ein weitere Klasse (die als Proxy dient) gemarshallt.

Das klappt soweit und ich kann die Library eigentlich problemlos nutzen. Nun muss die Library allerdings Dateien verarbeiten, die von irgendwo kommen - sprich die zu verarbeitenden Daten sind ab un zu einfach korrupt und das kann ich auch nicht unterbinden. Das kann nun dazu führen dass ich sog. Corrupted State Exceptions wie z.B. System.AccessViolationException um die Ohren bekommen gehauen krieg.
Nun sind diese Exceptions seit .net 4.0 nicht mehr einfach via "Catch-All" zu fangen, sondern die Methode, die das tun will muss explizit mit dem [HandleProcessCorruptedStateExceptions]-Attribut markiert werden (siehe Handling Corrupted State Exceptions)
Somit ist es (hoffentlich) dennoch möglich, ein Catch zu etablieren, in dem zumindest noch "aufgeräumt" wird (inkl. Freigabe der dedizierten AppDomain).

Soviel zur Vorgeschichte... Jetzt die eigentliche Frage: Reicht diese Vorgehensweise als Absicherung gegen eine z.B. System.AccessViolationException. Oder kann meine Haupt-Appdomain dadurch auch "korrumpiert werden"?
Eines der wichtigsten Ziele in der Applikation ist Stabilität und Fehlertoleranz. D.h., ich hab kein Problem damit, wenn die Nativen Calls letztlich in einer Exception münden - solange ich diese sauber fangen und angemessen darauf reagieren kann (d.h. Aufräumen um keine Memory-Leaks zu bekommen, Rückmeldung, dass der Aufruf schiefgeganen ist, kein weiteres Arbeiten mehr mit möglicherweise instabilen "Objekt-Resten", etc. pp.).
Wenn nein, was wäre dann "sicher"? Ich hab schon daran gedacht, die Native Calls in einen eigenen Prozess auszulagern - aber das wäre ein ziemlicher Overhead im Hinblick auf die Performance. Und das möchte ich nur dann umsetzen, wenn's wirklich nicht anders geht.

Kennt sich hier jemand tiefer mit der Materie aus? Die MSDN ist da nämlich IMHO mehr als dürftig...

Bart Simpson

12.04.2012 - 18:39 Uhr

Wenn ich in der GROUP BY Klausel in char konvertieren, erhalte ich eine Fehlermeldung. Dort muss der Datentyp mit dem in der DB Vorgegebenen übereinstimmen wies aussieht.

Nein, Du kannst gruppieren nach was immer Du willst - auch nach einem Ausdruck der ein COVERT enthält - wichtig ist nur, dass Du nur die exakt selben Ausdrücke selektieren (mal abgesehen von Aggregat-Funktionen) kannst, nach denen Du auch gruppierst.

Bart Simpson

11.04.2012 - 13:54 Uhr

Das Problem mit deiner Lösung ist, nicht nach kombinationen aus Geschlecht und Geburtsjahr aggregiert wird, sondern nur nach Geschlecht. Oder sehe ich das falsch?..

Ja, das siehst Du falsch!

Die Klausel
GROUP BY E.Geschlecht ,
ISNULL(CONVERT(VARCHAR(20), YEAR(E.Geburtstag)), 'Angabe fehlt')

enthält 2 Ausdrücke (einmal nur eine Spalte, einmal einen berchneten Ausdruck), also wird auch nach den beiden gruppiert.

Bart Simpson

11.04.2012 - 10:20 Uhr

Beim durchlesen dieses Threads war ich jetzt doch ein wenig erstaunt... Ich persönlich finde VS 11 ja ganz gut - allerdings nur aus technischer Sicht (.net 4.5 im allgemeinen, Geschwindigkeitsoptimierungen, etc.). Die Optik stört mich aber dramatisch. Nichts gegen ein neues Design (ich bin sehr glücklich mit z.B. Office 2010) oder das Entfernen von oftmals unnötigen Menüs bzw. Symbolleisten (welcher Entwickler nutzt bitte nicht STRG-C und Konsorten und klickt stattdessen auf die Icons in der Toolbar???) - das war IMHO dringend nötig.

ABER: Der Wiedererkennungswert der Icons (aller Icons, also auch und vor allem Toolbars, im Solution Explorer, etc.) ist für mich nahe bei NULL. Und das behindert mich massiv beim Arbeiten. Und meine sämtlichen Entwickler-Kollegen sind da der selben Meinung.
Hier im Forum hingegen scheint eine gegenteilige Meinung zu herrschen - und das hätte ich nicht erwartet. Bin ich etwa sooo anders? 🤔

Bart Simpson

11.04.2012 - 09:57 Uhr

Hi,

soweit ich das sehe, sind da zwei Probleme vorhanden:

1.) Du kannst nicht Ausgabewerte unterschiedlichen Typs in einer Spalte mischen. YEAR(Geburtstag) liefert int, 'Angabe fehlt' ist aber ein varchar.
Das bedeutet, Du musst auch die Werte für die Jahre in varchar umwandeln, z.B. mit CONVERT(VARCHAR(20), YEAR(Geburtstag)).

2.) Die Ausdrücke in der GROUP BY Klausel müssen identisch (!) sein mit denen in der SELECT Klausel. Du kannst Dich nicht einmal auf YEAR(Geburtstag) beziehen und ein anderes mal nur auf Geburtstag.

Diese beiden Punkte angewandt, kommt folgendes dabei raus:

SELECT Geschlecht, CASE GROUPING (CONVERT(VARCHAR(100), YEAR(Geburtstag)))WHEN '1' THEN 'gesamt'
WHEN '0' THEN (CASE WHEN CONVERT(VARCHAR(100), YEAR(Geburtstag)) IS NULL THEN 'Angabe fehlt' ELSE CONVERT(VARCHAR(100), YEAR(Geburtstag)) END)
END AS Geburtsjahr,
MAX(Einkommen) AS MaxEinkommen
FROM Einwohner
GROUP BY ROLLUP (Geschlecht, CONVERT(VARCHAR(100), YEAR(Geburtstag)))

Ich habe allerdings noch nie in dieser Verwendung mit ROLLUP und GROUPING() gearbeitet... Ich für meinen Teil würde erst meine Werte berechnen lassen und dann aggregieren:

SELECT E.Geschlecht,
ISNULL(CONVERT(VARCHAR(20), YEAR(E.Geburtstag)), 'Angabe fehlt') AS Geburtsjahr,
MAX(Einkommen) AS MaxEinkommen
FROM dbo.Einwohner AS E
GROUP BY E.Geschlecht,
ISNULL(CONVERT(VARCHAR(20), YEAR(E.Geburtstag)), 'Angabe fehlt')

Bart Simpson

10.04.2012 - 11:00 Uhr

Hi,

also ich bin mir ja nicht sicher, ob ich die eigentliche Fragestellung richtig verstehe, aber ich versuch mal trotzdem meine Sicht hier widerzugeben - und zwar ein auch wenig aus der mathematischen Perspektive.

Du hast also ein Arry mit den X und Y Werten (also eine Wertetabelle) einer Dir im Prinzip unbekannten Funktion (will heissen, Du kennst den Funktionsterm nicht).
Was Du suchst ist eine Stelle am entsprechenden Funktionsgraphen, bei dem die Steigung den Wert -1 hat.
Soweit korrekt?

Wenn ja, dann bin ich der Meinung, das Ganze steht und fällt mit der "Auflösung" Deiner Wertetabelle (bzw. Deinen Ansprüchen an die Ergebnisse). Die Ableitung einer Funktion an sich ist ja definiert als der Grenzwert von Delta(Y) / Delta(X) mit Delta(X) gegen 0 (Formeln zu schreiben ist hier ein wenig umständlich...).
Da Du nun aber keinen Funktionsterm (mit dem Du die Wertetabelle an jeder beliebigen Stelle mit theoretisch beliebiger Genauigkeit füllen könntest) hast, sondern nur "ein Paar" diskrete Werte (die konkrete Anzahl ist erst mal unerheblich), bleibt Dir eigenlich nur ein Ansatz wie folgender:

Du errechnest für alle Einträge aus deiner Wertetabelle (und deren "Nachbarn") jeweils Delta(Y) und Delta(X). Damit hast Du im Prinzip das Steigungsdreieck zwichen den jeweiligen Punkten. Jetzt gibt's zwei Möglichkeiten:
a) Die Werte für Delta(X) sind klein genug (d.h. nahe bei Null) um Deinen "Qualitätsansprüchen" zu genügen. Dann musst Du nur noch kucken, ob sich für die jeweils berechneten Werte Steigungswerte ergeben, die nahe genug bei Deinem Zielwert von -1 liegen (was typischerweise heisst m + 1 < Epsilon, wobei Epsilon z.B. 1/1000, 1/10000, ... oder sowas in der Richtung ist.)

Fall b) Deine Delta(X) Werte sind leider zu groß.
Aus rein methematischer Sicht hast Du somit keine direkte Möglichkeit die gesuchten Stellen zu finden (von Glückstreffern mal abgesehen). Du hast (zumindest sehe ich im Moment keine andere Chance, aber ich lass mich gerne korrigieren) nur die Möglichkeit, Zwischenwerte zu raten / abzuschätzen und Dich damit anzunähern. Typischerweise wird sowas mit einer Interpolation erledigt.
In Deinem konkreten Fall würde ich zu sowas wie Beziér-Kurven tendieren und die jeweiligen Punkte in der Umgebung der gewählten potentiellen Stelle aus Deiner Wertetabelle als Stützpunkte zu nutzen.
Wie zommi schon erwähnt hat, gibt es aber unendlich viele Kurven, die an der Stelle passen könnten - d.h. die Abweichungen, die damit "erzielt" werden können sind extrem stark abhängig vom Abstand der vorhandenen Punkte. Vereinfacht gesagt: Je näher diese beieinander liegen, desto genauer wird die Annäherung (was dich im Prinzip zu Fall a) zurückbringt).

Wenn Du nichts über den Ursprung der Punkte (=die Funktion) weisst, und die Werte zu weit auseinander liegen, dann wird das Ganze sehr schnell zu einem Glücksspiel, bei dem Du möglicherweise ganz gute Näherungen erzielen kannst, aber möglicherweise auch meilenweit daneben liegen kannst.
Dein Vorschlag, den Funktionsterm zu erraten, wird, wenn Du nichts darüber weisst, auf im Prinzip genau das selbe herraus laufen. Egal welche Methodik hierfür verwendet wird, es hängt alles an der Anzahl und Dichte der zugrunde liegenden Wertepaare. Je weniger Du interpolieren musst (weil es schon als Wert vorliegt) umso näher landest Du am Orignal - und dummerweise gilt natürlich auch die Umkehrung.

Bart Simpson

29.02.2012 - 14:29 Uhr

Hallo,

ich versuche grade den "empfohlenen Weg" rauszufinden für ein Problem mit ASP.net... Sämtliche Guides, Tutorials, etc. die ich finden konnte sind nämlich immer so eine Art Proof-of-Concept und hören typischerweise da auf, wo's spannend wird 😜

Zum Thema: Es geht um eine Mehrschichtige Applikation. Sämtliche Datenbankzugriffe und die Business-Logik werden durch einen WCF-Dienst abgebildet. Diesen WCF-Dienst nutzen dann versch. Clients, einer davon eine ASP.net WebForms Applikation.
Nun soll natürlich auch sowas wie Benutzeranmeldung und was damit in Zusammenhang steht an einer zentralen Stelle eingebaut werden und für alle Clients gleich sein - also muss das in den WCF Dienst. Das ist soweit auch überhaupt kein Problem. Spannend wird's jetzt aber, wenn als Client die ASP.net Anwendung angedockt wird... Was genau muss in der Web-Forms-Applikation gemacht werden?

Ich hab mir einige Tutorials auf http://www.asp.net/web-forms angesehen und komme zu dem Schluss, dass sich das mit einer Custom-Implementierung für den MembershipProvider, IIdentity und IPrincipal lösen lassen sollte, wobei erstgenannter z.B. die Anmeldedaten durchreichen kann.
Grundlegende Frage: Ist das korrekt? Oder gibt es für mein Szenario bessere/empfohlene Ansätze? Ich bin ja der Meinung, dass so eine Applikations-Architektur nichts aufregendes sein sollte, also sollte es da doch quasi einen "Standardweg" geben...

Mit der Custom-Implementierung bekomme ich es nun soweit hin, dass ich mich bei der Web-Forms Anwendung anmelden kann, wobei die Prüfung der Daten durch den WCF-Dienst geschieht.
Genau diese Prüfung geschieht nun aber im CustomMembershipProvider in der Methode ValidateUser(...).
Wo lege ich nun Daten wie z.B. die mir vom WCF-Dienst verpasste Session-Id ab, damit ich sie bei späteren Aufrufen z.B. in den Pages nutzen kann? In der Session? Existiert die da schon (und zwar "sauber")? Scheint zwar so, allerdings scheint die dann anders "abzulaufen" als das zugrunde liegende FormsAuthenticationTicket...

Bin für Tips (und gerne auch Tutorials die etwas tiefer gehen) dankbar 😁

Bart Simpson

23.02.2012 - 09:31 Uhr

Sieht eigentlich ok aus. Also testweise würde ich genau so vorgehen wie Du: Einfach mal andere Namen verwenden.

Du kannst ja mal in der Registry unter HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog nachschauen. Da müsstest Du Dein Log bzw. die Source finden.

Ansonsten bin ich auch langsam überfragt 🤔

Bart Simpson

22.02.2012 - 20:15 Uhr

Ich hab vor nicht allzu langer Zeit was ähnliches entwickelt (ging um ne Software zur Anbindung an eine Ring/Teiler-Auswertemachine).
Was ich daraus gelernt hab: Selbst bei fachlichen Know how, kommst Du ohne Doku des Protokolls das über den COM-Port gesprochen wird nicht weiter.
Ob Du mit Reverse-Engineering (decompiling) zu etwas vergleichbarem kommst, kann ich nicht sagen... Aber dran zweifeln würde ich heftig 🙁

Bart Simpson

22.02.2012 - 17:51 Uhr

Klingt für mich danach, als ob Du das nicht sauber prüfst..

Aus EventLog Class

if(!EventLog.SourceExists("MySource"))
        {
             //An event log source should not be created and immediately used.
             //There is a latency time to enable the source, it should be created
             //prior to executing the application that uses the source.
             //Execute this sample a second time to use the new source.
            EventLog.CreateEventSource("MySource", "MyNewLog");
            Console.WriteLine("CreatedEventSource");
            Console.WriteLine("Exiting, execute the application a second time to use the source.");
            // The source is created.  Exit the application to allow it to be registered.
            return;
        }

Bart Simpson

22.02.2012 - 17:47 Uhr

Die Frage ob man Shell Extension mit .net machen kann/sollte, beantworte ich mal mit einem klaren JEIN :evil:
Ja, es ist möglich und dank SxS in .net 4 sollte es theoretisch auch kein Problem darstellen. Allerdings ist sich selbst Microsoft noch nicht so ganz sicher, ob es nicht doch noch zu "Nebenwirkungen" kommen kann und deshalb ist es nach wie vor nicht supported. Und diese Aussage stammt von den Jungs die für die Codebeispiele in Microsofts All-in-one-Code-Framework zuständig sind.

Siehe dazu auch: Is it supported to write Windows Shell Extension using .NET 4 today?

Bart Simpson

22.02.2012 - 10:27 Uhr

Wenn ich das richtig verstehe, willst Du in eine eigenes Eventlog für den Dienst schreiben. Dazu muss das Eventlog aber erst mal angelegt werden - und dazu brauchtst Du Admin-Rechte. Darüber bin ich schon desöfteren gestolpert... Erste Ausführung des Dienstes als Admin, danach erst als Low-Privilege-User hat sich da als Methodik bewährt.

Bart Simpson

22.02.2012 - 10:22 Uhr

Die Funktionen des neuen SQL Servers sind dahingehend recht interessant, ist aber noch BETA.
Es gibt aber auch noch anderer Ansätze, die Du verfolgen könntest:

  • Du könntest via ASP.net einen WebDAV Server erstellen, der seine Daten in die DB schreibt / aus der DB liest. WebDAV wiederum kannst Du dann sehr einfach als Laufwerk mappen.

  • Es wurde auch schon erwähnt "einen eigenen Explorer" zu schreiben. Stattdessen kannst Du auch den Windows-Explorer erweiteren. Stichwort "Shell Namespace Extension". Das sollte aber (zumindest der Teil, der in den Explorer geladen wird) nicht in .net erfolgen.

Bart Simpson

22.02.2012 - 10:03 Uhr

Vielen Dank erst mal für die Ideen!
@dN!3L: Den anderen Thread fand ich sehr lesenswert... hatte ihn leider vorher nicht gefunden, weil ich wohl blöde Suchbegriffe verwendet hab 🤔

Die Audit Funktionen wären sehr nett, aber wie's aussieht bekomm ich nur maximal eine Standard Edition - von daher fällt das wohl flach.
Ansonsten sind die Ideen schon relativ ähnlich zu dem von mir angedachten - kling also schon mal nach einem nicht ganz schlechten Weg 😉

Was ich noch nicht in Erwägung gezogen hatte war die Speicherung als XML. Das klingt echt vorteilhaft. Grade weil ich dann mehrere Tabellen (bzw. die Änderungen an deren Datensätzen) in ein und der selben Struktur verwalten könnte.

@Khalid: Wär's evtl. möglich da mal ein bisschen Sample-Code aus so 'nem Trigger zu sehen? Wäre u.U. interessant zu sehen, ob du da die selben Ansätze verfolgtst wie ich, oder evtl. völlig anders vorgehst.

Bart Simpson

21.02.2012 - 15:48 Uhr

Ich grüble grad über "den besten" Ansatz für eine Protokollfunktion auf Datensatzebene bin aber unentschlossen, was denn nun am geschicktesten wäre... Evtl. kann mir ja jemand mit Erfahrungen in der Richtung weiterhelfen.

Zum Hintergrund: Eine Applikation schreibt (letztenendes über einen Webservice) Änderungen an Datensätzen in eine Datenbank (SQL 2008 R2).
Dabei soll protokolliert werden, welcher User welche Änderungen vorgenommen hat. Ein "Zurückrollen" auf eine Vorgängerversion wäre dabei zwar nett, ist aber keineswegs zwingend gefordert. Es geht also grob vereinfacht darum den "Schuldigen" zu finden :evil:

Nun gibt's da ja prinzipiell verschiedene Ansätze, z.B.*Trigger *Business-Logik im Webservice *Business-Logik in der Client-Applikation (wobei das aus Sicherheitsgründen wohl ausscheidet)

um überhaupt erst mal die Änderungen zu finden. Desweiteren stellt sich die Frage, wie die Informationen dann persistiert werden. Das soll grundsätzlich strukturiert erfolgen (um eine Auswertung á la "User1 hat an Datensatz#2 das Feld1 von 'Test' auf 'xxx' geändert" zu ermöglichen).
Ein Ansatz wäre es nun genau diese Information in einer dafür dedizierten Struktur abzulegen.
Eine andere Möglichkeit ist z.B. immer eine Kopie des Datensatzes zu erstellen, die (mal abgesehen von Metadaten wie Datum und User) identisch zum Original ist (vgl. Versionshistorie bei Wikipedia-Seiten). Damit würde auch gleich die "Rollback"-Funktion ermöglicht.

Das sind nun in Summe eine Menge an Optionen, Möglichkeiten und Ansätzen. Und es gibt sicher noch viele mehr... Ihr dürft sie gerne hier erwähnen 😁
Aber was davon geschickt ist und was eher nicht (quasi so eine Art "best practice"), darüber hab ich bisher nicht viel in Erfahrung bringen können.

Irgendwelche Hinweise? Ratschläge? Links?

Bart Simpson

21.02.2012 - 14:40 Uhr

Unter "neueren" Windows Versionen (z.B. Win7) gibt's auch die Möglichkeit den Dienst "verzögert" zu starten (ist einfach eine weitere Option in den Diensteigenschaften). Das hat mir schon bei vielen änhlich gelagerten Problemen geholfen.

Bart Simpson

21.02.2012 - 14:36 Uhr

Also theoretisch sollte etwas in der Art (Achtung: ungetestet, mit notepad erstellt!) funktionieren:

public IEnumerable<string> GetItems()
 {
	 lock (lockObject)
	 {
		try
		 {
			using (var connection = OpenConnection())
			{
				using (OleDbDataReader reader = commandSelectItems.ExecuteReader())
				{	
					 if (reader != null && reader.HasRows)
					 {
						 findOrdinalColumnNumbers(reader);

						 while (reader.Read())
						 {
							 string foundItem = reader.GetString(indexItem);
							 if (Überprüfung(foundItem))
							 {
								 yield return foundItem;
							 }
						 }
					}
				}
			}
		 }
		 catch (Exception ex)
		 {
			 throw new InvalidOperationException("Fehler beim Lesen der Datenbank.", ex);
		 }
	 }
 }

Das finally-Konstrukt würde ich allerdings zugunsten eines weiteren usings (wie angedeutet) rauswerfen.

Ob das Ganze nun Sinn macht, oder nicht - das steht auf einem ganz anderen Blatt. Da das yield ja nun in jeder Iteration in den aufrufenden Code "zurückspringt" kann's da schon zu Problemen kommen, wenn der "äußere" Code z.B. recht lange läuft. Dann kann's Timeouts hageln...

Grundsätzlich sollte aber eigentlich erst mal nichts gegen dieses Pattern sprechen.

Bart Simpson