Laden...

Forenbeiträge von Sarc Ingesamt 417 Beiträge

16.08.2011 - 23:02 Uhr

Das beigefügte T4-Skript ist als Ersatz für den ResXFileCodeGenerator gedacht (nur für Strings, keine anderen Resourcen wie Bilder etc.), welcher anhand von Resx-Dateien Quellcode erzeugt. Das T4-Skript lässt sich im Gegensatz zum ResXFileCodeGenerator leicht anpassen.

Hintergrund:
Der bevorzugte Weg um eine .NET Anwendung übersetzbar zu gestalten führt über Resourcen / Resx-Dateien. Anhand der Daten einer Resx-Dateien, erzeugt das standardmäßige Custom Tool ResXFileCodeGenerator eine Resourcen-Klasse, über die der Zugriff auf die übersetzbaren Texte möglich ist.

Schwachstelle des ResXFileCodeGenerator:
Leider bietet der ResXFileCodeGenerator keine Eingriffsmöglichkeiten in den generierten Quelltext und ist somit nicht erweiterbar. An manchen Stellen (z.B. in Attributen) muss man manchmal den Namen eines zu übersetzenden Wertes angeben, wie beispielsweise hier (Name = "Password"):

[Display(ResourceType=typeof(Strings), Name = "Password")]
public string Password { get; set; }

Das ist fehleranfällig, da eine Änderung des Namens in der Resourcendatei nicht festgestellt werden kann und zur Laufzeit einen Fehler erzeugt.

Ok, jetzt zum T4-Skript:
Wer (noch) nicht weiss, was T4 ist, der kann sich hier ein wenig informieren: T4 (Text Template Transformation Toolkit) Code Generation - Best Kept Visual Studio Secret

Allen T4-Dateien (*.tt) ist standardmäßig das Custom Tool TextTemplatingFileGenerator zugewiesen. Normalerweise
können diese Dateien über den Contextmenüpunkt "Run Custom Tool" ausgeführt werden. Da wir jedoch nicht immer manuell
die Generierung anstossen möchten, verwenden wir das Custom Tool T4ScriptFileGenerator.
Hierfür wird zusätzlich das T4-Toolbox benötigt, welches hier runtergeladen werden kann: http://t4toolbox.codeplex.com/

Das Custom tool T4ScriptFileGenerator wird dann der *.resx-Datei als Custom Tool zugewiesen, d.h. es ersetzt das standardmäßige custom tool ResXFileCodeGenerator. Dadurch wird nach jeder Speicherung der *.resx-Datei die Code Generierung des T4-Skripts angestossen.

Das ganze sieht dann im Solution Explorer etwa wie folgt aus, wobei Strings.tt hier das eigentliche T4-Skript ist (wichtig ist das die Namen identisch sind, also Strings.tt/Strings.resx):
-> siehe nächster Post

Ein Beispielprojekt, inklusive des T4-Skripts (Strings.tt) ist unten angefügt.
Wie dort zu erkennen ist, erstellt das Skript zusätzlich eine Klasse (Name ist konfigurierbar), welche die Namen der Resourcen enthält:

public static partial class ResourceNames
{
       	public const string FileNotFound = "FileNotFound";
       	public const string Title = "Title";
       	public const string Today = "Today";
}

Auf diese Werte kann im Anwendungscode verwiesen werden. Da diese bei jeder Änderung neu erzeugt werden, sind Änderungen sofort zu Compilezeit feststellbar.

Ein weiteres Feature ist die Unterstützung von Formatierungsparametern in der Resourcendatei. Normalerweise lassen sich übersetzbare Parameter im Text etwa wie folgt schreiben:

Die Datei '{0}' wurde nicht gefunden.

Der Anwendungscode ruft dann meist string.Format mit den entsprechenden Parametern auf.
Das T4-Skript nimmt einen gewissen Teil dieser Arbeit ab. Und zwar können spezielle Parameter im Text definiert werden,
welche vom T4-Skript entsprechend interpretiert werden. Das Format ist: {t:n} wobei t für den Typ des Parameters und n für den Namen steht. t ist optional, d.h. wenn t nicht angegeben wird ({:n}), dann wird als Typ des Parameters object gesetzt. Obiger Text könnte also so geschrieben werden:

Die Datei '{s:filename}' wurde nicht gefunden.

Das 's' steht für den Typ string. Das T4-Skript erzeugt dann daraus keine Eigenschaft, sondern eine Methode mit den entsprechenden Parametern. In diesem Fall eine Methode mit dem Parameter 'filename' vom Typen string:

/// <summary>
/// Die Datei '{s:filename}' wurde nicht gefunden.
/// </summary>
public static string FileNotFound(string filename, IFormatProvider formatProvider = null)
{
	...
}

Die generierte Klasse heisst in dem Beispiel Strings, daher könnte die obige Methode wie folgt aufgerufen werden:

Strings.FileNotFound("test.txt")

Ich hoffe jemand kann damit was anfangen 😃

Schlagwörter: T4, Resx, Resourcen, Übersetzung, Generator

11.08.2011 - 11:47 Uhr

Hallo,

also im Konstruktor Threads zu starten finde ich nicht grade gut, aber ist hier nicht das Thema.
Du kannst AutoResetEvent verwenden:

public class A
{
	private AutoResetEvent ev = new AutoResetEvent(false);
	private List<object> bList;

	public A()
	{
		// Threads
		ThreadPool...(callback_methode);
	}

	void callback_methode()
	{
		bList = ...
		ev.Set();
	}

	public List<object> Bs
	{
		get
		{
			ev.WaitOne();
			return bList;
		}
	}
}
11.08.2011 - 10:37 Uhr

Mit Verweis auf PersonRepository meinst du den Verweis auf die Assembly in der PersonRepository definiert ist oder?
Wichtig ist letztendlich nur, dass du in der Klasse A die Abhängigkeit zu einer Schnittstelle (in dem Fall IRepository<Person>) und nicht zu einer konkreten Implementierung hast.
In welcher Assembly die spätere konkrete Implementierung dafür dann liegt, ist aus meiner Sicht nicht so wichtig.

11.08.2011 - 10:21 Uhr

Hallo,

ich sehe irgendwie den Zusammenhang zum DI nicht. Es geht dir doch rein
um die Aufteilung der Klassen in Assemblies oder hab ich das falsch verstanden?
Für ein DI ist es ja egal in welcher Assembly die jeweilige Komponente liegt.

11.08.2011 - 08:26 Uhr

Gibt es da eine Möglichkeit per SQL-Statement?

Hört sich so an als suchst du nach einem LEFT JOIN. http://www.w3schools.com/sql/sql_join_left.asp

10.08.2011 - 14:34 Uhr

Es überrascht mich immer wieder was für Augenkrebs erzeugende Konstrukte mit C# möglich sind.
Scheint zwar zu klappen aber die Lesbarkeit ist ein graus 😦

Das mit dem Einzeiler ist bewusst etwas übertrieben, aber generell sollte man die Features von C# schon ausnutzen, ansonsten kann ich ja gleich Java coden 😛

Beispiel:

int zeroBytes = 0;

for (int i = 0; i < bytes.Length; i++)
{
    byte b = bytes[i];

    if (b != 0)
        break;

    zeroBytes++;
}

gegen

int zeroBytes = bytes.TakeWhile(f => f == 0x00).Count();

Ich finde letzteres wesentlich knackiger und lesbarer.

10.08.2011 - 14:02 Uhr

Oder so:

var bytes = new byte[] { 0xBE, 0x06, 0x00, 0x00 };
var zeroes = 0;
bytes = bytes.Reverse().SkipWhile( (f,i) => { zeroes = i; return f == 0x00; }).ToArray().Concat(Enumerable.Repeat<byte>(0x00, zeroes)).Reverse().ToArray();
10.08.2011 - 13:04 Uhr

Hallo,

du brauchst einfach nur groupieren und das Minimum finden.
Um das Beispiel von Taipi88 aufzugreifen:

static void Main(string[] args)
{
	var list = new List<ITest>();
	list.Add(new A() { Min = 1, Max = 2 });
	list.Add(new A() { Min = 0, Max = 3 });
	list.Add(new B() { Min = 5, Max = 20 });
	list.Add(new B() { Min = 3, Max = 50 });

	var dict = list.GroupBy(f => f.GetType()).ToDictionary(k => k.Key, v => v.Min(x => x.Max));
	// dict[typeof(A)] == 2
	// dict[typeof(B)] == 20
}

Damit erhälst du ein Dictionary<Type,int> mit den Typen und der jeweiligen Version.

09.08.2011 - 21:10 Uhr

Hallo,

in der Regel gehört der Quelltext schon zur Arbeit. Wenn die Software ein essenzieller Bestandteil deiner Arbeit ist (und nicht nur ein 'Gimmick'), dann muss der Professor natürlich später die Qualität prüfen können. Evtl. könnten ja bestimmte Quelltexte auch einfach aus dem Internet kopiert worden sein (was ich nicht unterstellen möchte).

04.08.2011 - 11:52 Uhr

Hallo,

hast du es debuggt bzw. geprüft, ob das model auch wirklich neu erzeugt wird?

04.08.2011 - 10:48 Uhr

Hallo,

1.) Nimm einfach das Bild als Background-Image und leg eine Tabelle mit dem entsprechenden Raster drüber (Zellenbreite/höhe 50 px).
2.) Lässt sich leicht mit nem mouse-over event realisieren (einfach border der selektierten Zelle umfärben)
3.) Du musst ein Teil des Bildes ausschneiden (50x50). Evtl. einen Ajax-Request mit dem Namen des Bildes und den passenden Bereich schicken und das Bild serverseitig zuschneiden und in der Session hinterlegen.
4.) Bei einem on-click event, holst du dir per ajax den bildausschnitt aus der session und fügst es in die selektierte Zelle ein.

Alternativ kannst du das bild ja schon vorher in 50x50px Teile schneiden und diese dann jeweils als hintergrund der Tabellenzellen verwenden.

03.08.2011 - 12:15 Uhr

Ähm, wie wärs mit ner statischen Methode?
Aber mal ehrlich: [Hinweis] Wie poste ich richtig? 1.1.1

03.08.2011 - 09:25 Uhr

Hallo,

mögliche Libs wurden von Nitro2k7 ja schon genannt.
Grob gesehen hast du zwei Möglichkeiten. Entweder du generierst das komplette
Dokument mit der Lib, d.h. Header, Footer, Inhalt usw. Oder du erstellst dir ein
PDF-Formular, in dem du das Layout und notwendige Felder definierst und die Werte
der Felder dann später mit Hilfe der Lib setzt.
Beispiel: Fill in PDF Form Fields using the Open Source iTextSharp DLL

Ich habe mir z.B. mit Open Office Draw ein PDF-Formular erstellt und das mit iTextSharp gefüllt. Klappt wunderbar.
Es kann natürlich sein, dass ein festes Formular für deinen Anwendungszweck nicht dynamisch genug ist, dann musst du alles selbst generieren.

02.08.2011 - 19:50 Uhr

Hallo,

Du sagst ja du brauchst eine "Unique" Liste, daher sieht das für mich nach einem Fall für Distinct() aus.
Beispiel:

var portal = "portal1";
var kunde1 = new Kunde();
kunde1.Portale.Add(portal);
			
var kunde2 = new Kunde();
kunde2.Portale.Add(portal);
kunde2.Portale.Add("portal2");
			
var monat = new Monat();
monat.Kunden.Add(kunde1);
monat.Kunden.Add(kunde2);
			
var monatList = new List<Monat>();
monatList.Add(monat);

var distinctPortals = monatList.SelectMany(f => f.Kunden.SelectMany(x => x.Portale)).Distinct().ToList();
31.07.2011 - 22:41 Uhr

Hallo,

sieht nett aus. Aber wieso hast Du dich gegen die vorhandene Funktionalität aus System.ComponentModel.DataAnnotations entschieden?
Es ist zwar primär für Asp.NET MVC ausgelegt, aber lässt sich auch anderweitig nutzen. Schön ist auch, dass die Validierungssachen in Meta-Klassen ausgelagert werden können, z.b wie im Beispiel hier: RegularExpressionAttribute

27.07.2011 - 11:53 Uhr

Den Post hab ich gelöst, nur der Response funktioniert nicht.

Was heisst "funktioniert nicht"?

27.07.2011 - 11:22 Uhr

Hallo,

dazu kannst Du die WebClient-Klasse nutzen. Siehe: http://www.daveamenta.com/2008-05/c-webclient-usage/

24.07.2011 - 11:30 Uhr

Hallo,

ich denke dazu brauchst du die MvcContrib (Strongly Typed RedirectToAction).

20.07.2011 - 14:35 Uhr

Hallo,

prüf doch erstmal, ob der Aufurf überhaupt stattfindet.

mTestClassMock.Setup(mock => mock.MethodToTest(It.IsAny<ProcessArgument>())).Returns(bla);
...

mTestClassMock.VerifyAll();
17.07.2011 - 21:32 Uhr

Hallo,

zu 1)
Einfach Rechtsklick auf die Datei ('Öffnen mit...') und CSharp Editor als Default wählen. Dann kommst Du immer per Doppelklick in die Code-Datei.
zu 2)
Strg+, (Strg und Komma) drücken. Dann Suchbegriff eingeben.

16.07.2011 - 21:19 Uhr

Hallo,

das geht mit dem is-operator (methodType is IList).
Sind aber Grundlagen.

16.07.2011 - 14:30 Uhr

Hallo,

Du schreibst "sollte am Join liegen", aber ich seh hier keinen join...
Wie hängen tbl_Rechnungen und tbl_Buchungen denn zusammen?

16.07.2011 - 12:29 Uhr

Hi,

das folgende Pattern macht was Du willst:

(?<![?]):
04.07.2011 - 23:26 Uhr

das war schon klar 😉
Das Constraint sagt ja, dass T das IHtmlTag implementieren muss.
Später wird bei public T Id() dann this as T zurückgegeben, obwohl "this", also weder IHtmlTag<T>, noch HtmlTag<T> das IHtmlTag interface implementieren.
Und nun?

04.07.2011 - 23:00 Uhr

Ich meinte eigentlich den gesamten Source-code. Ganz verstehe ich noch nicht wie die folgende Lösung funktionieren soll:

interface IHtmlTag<T> where T: IHtmlTag
{
  T Id();
}

class HtmlTag<T>: IHtmlTag<T>
{
  public T Id()
  {
     return this as T;
  }
}

HtmlTag<T> und die abgeleiteten Klassen implementieren doch IHtmlTag (nicht das generische Interface) nicht. wie kann da der Cast später gut gehen? Für was ist eigentlich das nicht-generische Interface?
Oder überseh ich grad was?

04.07.2011 - 22:49 Uhr

Hallo,

wie sieht denn die funktionsfähige Lösung jetzt aus?

04.07.2011 - 19:56 Uhr

Hallo,

eine Möglichkeit wäre z.b. eine separate Extension-Method:

public static class Extensions
{
	public static T FirstOrDefault<T>(this IEnumerable<T> source, Func<T, bool> predicate, Func<T> defaultFunc)
		where T : class
	{
		var result = source.FirstOrDefault(predicate);

		if (result != default(T))
			return result;

		return defaultFunc();
	}
}
public IAccount GetFirstActiveAccount(string hoster)
{
        var acc = accList.FirstOrDefault(x => x.Hoster.Name == hoster && x.Active == true, () => GetNewEmptyFreeAccount(hoster));
        return acc;
}
01.07.2011 - 10:45 Uhr

Zum Thema Singleton muss ich sagen, dass ich das Singleton zu testzwecken nach dem schema "Fourth version - not quite as lazy, but thread-safe without using locks" von
>
umgesetzt habe, was aber keinen Einfluss hatte. Sobald Du der Klasse einen öffentlichen Konstruktor verpasst, ist es aber kein Singelton mehr...

24.06.2011 - 17:15 Uhr

Hallo,

hast du dir schonmal AvalonEdit (http://wiki.sharpdevelop.net/AvalonEdit.ashx) angeschaut?
Evtl. kannst du das nach deinen Bedürfnissen erweitern, oder dir die Logik für das Folding abschauen.

20.06.2011 - 15:48 Uhr

// Edit: Seh ich das richtig, dass "moq" erst ab .NET 3.5 verwendet werden kann?

Ja, für aktuellste Version schon. Moq ist aber wirklich empfehlenswert. Ich möchte es nicht mehr missen.

20.06.2011 - 11:36 Uhr

Hallo,

was Du da machst klingt eher nach einem Integrationstest.
Lager den Zugriff auf den Cache in eine separate Komponente, dann kannst Du den Cache für deinen Unit-Test auch gut "mocken".

08.06.2011 - 10:37 Uhr
foreach(var line in File.ReadAllLines("filename").Where( f => !f.TrimStart().StartsWith("//") ) )
	Console.WriteLine(line);
02.06.2011 - 21:28 Uhr

Wie sollen Applikationen wie Office,
VisualStudio, Branchensoftware, Messenger,...
eigentlich alle Desktopapplikationen die "etwas mehr" können
als eine Webseite 😉 mit HTML5 und JS entwickelt werden???
Kann ich mir nicht vorstellen...

So abwegig ist das nicht, auch wenn es momentan "unvorstellbar" ist.

Beispiel für web-basiertes Office: http://www.microsoft.com/en-us/office365/online-software.aspx

Beispiele für eine web-basierte IDEs:
http://www.cloud-ide.com
http://www.coderun.com/studio/ (z. B. auch inkl. Debugging)

Die IDEs sind natürlich nicht 1zu1 zu einem lokalen Visual Studio zu vergleichen, aber ein proof-of-concept ist es allemal.

Microsoft ist ja in Sachen Cloud Computing "All in", daher wird es sicher eine Verlagerung Richtung Webanwendungen geben.

PS: Ich habe natürlich auch keine Lust auf JS-gefrickel und bevorzuge .NET.

02.06.2011 - 09:36 Uhr

Hallo,

grundsätzlich sollten keine generierten Binärdateien (z. B. /bin/ und /obj/ Ordner) und keine Benutzer-spezifischen Dateien (z. B. *.suo, *.user) in die Versionsverwaltung.

Gehören z.B. die Dateien im Properties Ordner eines Projekts zu einer Versionskontrolle?

Kommt drauf an, was Du in dem Ordner hast. Aber standardmäßig ist da ja die AssemblyInfo.cs drin, welche schon in die Versionsverwaltung gehört.

28.05.2011 - 14:59 Uhr

Hallo,

das Problem hier ist, dass das AsQueryable hier "zu spät" erfolgt.
Wenn Du es wie folgt machst, dann kannst Du die Expression korrekt auswerten:

var qry = (from c in Companies.AsQueryable() where c == "Microsoft" || c == "IBM" select c);
25.05.2011 - 12:49 Uhr

Hallo,

das genannte Beispiel bezieht sich auf eine ganz andere Codebasis.
Das sieht man schon an den Namespaces.

Die Methode die Du brauchst heisst ShowTextAligned und ist aus der Klasse PdfContentByte.cs
(public void ShowTextAligned(int alignment, String text, float x, float y, float rotation))
Ähnlich zu dem obigen Beispiel. Schau dir am besten den entsprechenden Sourcecode von iTextSharp an, dann kommst du sicher weiter.

25.05.2011 - 10:27 Uhr

Ok, das beschreibt ja so den Bereich von DoS, worum ich mich natürlich auch kümmern muss, z. B. Benutzer für n Minuten sperren, falls eine Ausführung länger als x Sekunden dauert. Und natürlich die Eingabe begrenzen wie Du gesagt hast.

Danke schonmal. Wer sich noch andere mögliche Probleme vorstellen kann, nur her damit.

24.05.2011 - 09:19 Uhr

Danke für die Antworten.

Solange Du immer nur einen Input zulässt nicht..

Was genau meinst Du damit?

@herbivore: Einen groben Check habe ich schon gemacht. Dateioperationen und Netzwerk-/Web-Zugriffe klappen schonmal nicht. Auch eine Thread-Kontrolle ala Thread.ResetAbort() ist damit nicht erlaubt.
Ich werde noch weiter nach möglichen Angriffsstellen suchen.

23.05.2011 - 19:49 Uhr

Hallo,

in meinem Szenario kompiliere ich beliebigen User-Input (C# Quelltext) on the fly als
Assembly und führe die Assembly dann in einer separaten AppDomain aus.
Diese AppDomain hat eigentlich keine Rechte, ausser eben für die Ausführung von Code:

var ps = new PermissionSet(PermissionState.None);
ps.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
// ... create appdomain, etc.

Die Ausführung läuft in einem separaten Thread, der nach einer Laufzeit von z.b. 10 sekunden automatisch die Ausführung beendet (um das Problem von Endlosschleifen einzufangen).
Ausserdem überwache ich alle paar millisekunden den Speicherverbrauch der AppDomain, um bei einer Überschreitung eines Schwellwertes ebenfalls auszusteigen.

Fallen euch vielleicht noch andere (sicherheitsrelevanten) Probleme ein, die mit so einer dynamischen Ausführung einhergehen könnten?

Edit: Ach ja, wichtig ist noch, dass die Ausführung auf einem (Web-)Server und nicht auf dem Client stattfindet.

19.05.2011 - 06:50 Uhr

Dann versuch mal

_grenzwert.GrenzMinMaximas.OrderBy( f => f.PosNr ).ToList()

und schau dir im Debugger an, ob was in der Liste ist.

18.05.2011 - 21:43 Uhr

Hallo,

wenn Du nach PosNr sortieren willst, sollte doch folgendes reichen:

_grenzwert.GrenzMinMaximas.OrderBy( f => f.PosNr )
18.05.2011 - 09:48 Uhr

Hallo,

DI bedeutet ja gerade eben, dass die Komponente in das Objekt "iniziert" wird und nicht, dass sich das Objekt die abhängigen Komponenten selbst beschaffen muss.
Hab mir den Artikel zwar nicht durchgelesen, aber das factory.Resolve sieht wie ein Service Locator aus.
Dadurch wirst Du an dieser Stelle natürlich wieder abhängig zum DI-Container, was ja nicht Sinn und Zweck ist.
Ausserdem ist die Testbarkeit besser, wenn Du die Versorgung der Abhängigkeiten über den Konstruktor regelst. Ansonsten musst Du Dir für das Testen erstmal eine Factory (oder Mock) basteln, damit die Abhängigkeiten korrekt aufgelöst werden.

17.05.2011 - 14:45 Uhr

Was spricht gegen:

public abstract class Base
{
  [...]
  public virtual string FriendlyType
  {
    get { return "Unbekannt"; }
  }
}

public class Derived1 : Base
{
  [...]
  public override string FriendlyType
  {
    get { return "Abgeleitete1"; }
  }
}

static void Delete<T>(IEnumerable<T> objects)
  where T : Base
{
  foreach (T obj in objects)
    if (!obj.Delete())
      MessageBox.Show("Fehler: " + obj.FriendlyType
 + " " + obj.ToString() + " konnte nicht gelöscht werden.");
}

16.05.2011 - 17:58 Uhr

Nein leider nicht, dass hatte ich schon getestet.
Aber mittlerweile denke ich, dass das Problem daran liegt, dass die erzeugte AppDomain nicht unter Full-Trust läuft und daher das laden der Assembly auch nicht erlaubt ist.

16.05.2011 - 17:13 Uhr

Hallo,

ich habe momentan folgendes Problem:
Ich erzeuge eine neue Assembly (mittels CSharpCodeProvider) im Speicher und erstelle danach eine neue AppDomain. Jetzt möchte ich in dieser neuen AppDomain diese temporäre Assembly nutzen. Wenn ich die Assembly nicht im Speicher erstelle, sondern physikalisch als Datei ablege, klappt alles. Aber anders leider nicht.
Hier ein bisschen Code:

Assembly asm = // ... Assembly mittels CSharpCodeProvider erzeugen
Type someType = asm.GetType("..."); // Auslesen eines Typs (für das untere Beispiel wichtig)
AppDomain domain = AppDomain.Create(...); // neue appdomain anlegen
var objectFromOtherDomain = domain.CreateInstanceAndUnwrap(...); // MarshalByRef-Objekt aus anderer AppDomain erzeugen
objectFromOtherDomain.DoStuff(someType); // z. B. einen Typ aus der temporär erzeugten Assembly übergeben --> hier kracht es, da die neue AppDomain die temporäre Assembly für den Typ someType nicht kennt

Fehlermeldung:
System.IO.FileNotFoundException: Could not load file or assembly 'bgj4u5rw, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

Hat jemand eine Idee, wie ich die temporäre Assembly auch in der anderen AppDomain verwenden bzw. bekanntmachen kann?

15.05.2011 - 12:36 Uhr

Das ist kein gültiger Ausdruck. Wenn dann schon so:


Regex regex = new Regex(@"(0[7-9]|10)");

12.05.2011 - 16:59 Uhr

das geht ja eben leider auch nicht weil das Service Model, kennt das DB Model ja nicht ergo kann ich die Aufgabe (DB Model) auch nicht im Service Model speichern

Hmm, in der OffeneAufgabeOderWiedervorlage-Klasse (Service Model) arbeitest Du doch mit der "Aufgaben"-Klasse aus dem DB-Model, also ist die Klasse ja im Service Model bekannt. Oder stammt dein Code nicht aus dem ServiceModel?

Aber vielleicht sollte man auch die Aufteilung der Schichten überdenken. Du schreibst ja:

Die Methode, führt diverse Prüfungen aus (if/else) und lädt dann ihrer seits je nach dem, entweder aus Tabelle a oder b einen DateTime wert.

Das klingt schon sehr nach Businesslogik und ist dann im Service Model vielleicht besser aufgehoben als in der DB-Schicht.

12.05.2011 - 15:40 Uhr

Hallo,

ich kenne die genaue Architektur zwar nicht, aber was spricht dagegen, die LadeWiedervorlageDatum-Methode nach der Query auszuführen? z. B. so (ungetestet):

for(int i = telefonnotizenOhneWiedervorlage.Count - 1; i >= 0; --i)
{
  var aufgabe = telefonnotizenOhneWiedervorlage[i].Aufgabe

  if( aufgabe.LadeWiedervorlageDatum(username) != null )
    telefonnotizenOhneWiedervorlage.RemoveAt(i);

}

Dann müsstest Du dir allerdings in dem Datenobjekt die Aufgabe merken.