Laden...
J
jnetrick myCSharp.de - Member
Software Engineer Bayern, Deutschland Dabei seit 03.03.2008 32 Beiträge
Benutzerbeschreibung

Forenbeiträge von jnetrick Ingesamt 32 Beiträge

14.10.2008 - 12:39 Uhr

Ist weder verrückt noch schwer 🙂 probiers mal so:


public static IEnumerable<T> SortListByProperty<T>(IEnumerable<T> list, string propertyname) {

			PropertyInfo Prop = typeof(T).GetProperty(propertyname);
			// sort
			IEnumerable<T> result = from item in list orderby Prop.GetValue(item, null) ascending select item;
			//oder
			//list.OrderBy(TObj => Prop.GetValue(TObj, null));

			return result;
		}

Du hast bei dir die propertyinfo zum sortieren verwendet und nicht den wert der property.

viel spaß

09.07.2008 - 09:21 Uhr

Vielen Dank für eure Antworten

Soweit ich das ganze jetzt verstanden habe, bedeutet das,
dass wenn ich AnyCPU verwende läuft mein .NET Program immer im optimalen Modus der darunterliegenden Platform. Wenn ich Unmanaged Code verwende muss ich darauf achten dass ich meinen Quellcode für die selbe Plattform kompiliere für die euch der von mir aufgerufene Unmanaged Code kompiliert wurde.

Ist es dann nicht empfehlenswert grundsätzlich AnyCPU einzustellen und nur wenn man Unmanaged Code verwendet auf x86 bzw x64 zu switchen?

Vermutlich ist dir das nur noch nicht über den Weg gelaufen, weil die meisten Java-Coder vermutlich noch nie einen native Call gebaut haben.

Habe ich sehr wohl svenson, musste mich zu dem Zeitpunkt aber noch nicht um 32-bit/64-bit kümmern. Ich vermute mal, dass ich in JAVA einfach zur Laufzeit die Plattform abfrage und je nachdem mit loadLibrary die richtige Library laden muss.
Ausserdem unterstützt JAVA sehr wohl COM über JNI.
Mit diesen Bibliotheken geht das sogar relativ einfach
https://com4j.dev.java.net/
http://jawinproject.sourceforge.net

08.07.2008 - 22:39 Uhr

Vielen Dank Tscherno für die schnelle Antwort. Einiges ist mir jetzt klar aber manche Sachen verstehe ich immer noch nicht so ganz:
Sollte der JIT nicht aufgrund der darunter liegende Plattform selbst entscheiden ob er 32 Bit oder 64 Bit Code erstellen soll. Bzw. was bewirkt dann AnyCPU.
Wenn der JIT durch die Einstellung AnyCPU automatisch den richtigen Code erstellt wofür gibt es dann überhaupt die anderen Einstellungen?
Ich finde diese Optionen irgendwie merkwürdig wenn ich das ganze mit JAVA vergleiche.
Hier gibt es nichts dergleichen und man kann einfach davon ausgehen, dass der JAVA JIT
-Compiler den für die entsprechende Plattform notwendigen Code generiert???

08.07.2008 - 14:05 Uhr

Hallo,
hat von euch schon jemand Erfahrungen mit den Auswirkungen dieser Einstellungen gemacht . Bzw. verstehe ich den Sinn der dahinter steckt nicht so ganz. Der .NET Code selbst ist doch eigentlich Hardware neutral und wird erst zur Laufzeit in Plattform spezifischen Code kompiliert. Wozu also überhaupt diese Konfigurationsoption.
Eines der Grundprinzipen des IL-Codes war es doch Plattformneutral zu sein!?
Ich bin etwas verwirrt ?(

Danke für eure Antworten

08.07.2008 - 13:59 Uhr

Hallo, ich habe ein Problem mit WebServices:

Wenn ich eine neue Service Reference hinzufüge kann man unter Advanced verschiedene Sachen einstellen unter anderem "Reuse types in all referenced assemblies" komischerweise interessiert Visual Studio sich bei mir überhaupt nicht für diese Einstellungen.

Auch die Einstellungen bei Collection type werden ignoriert. Anstatt generische Listen zu verwenden werden immer noch ganz normale Arrays generiert...

Mein eigentliches Problem ist, dass ich meine Business Entities z.B.
Customer aus dem generierten Code extrahieren möchte. Wenn also schon die normalerweise in der Service Reference generierten Typen schon irgend wo definiert wurden, soll VS diese nicht nochmal neu generieren. Wie gesagt leider funktioniert das ganze bei mir nicht X(. Was ich noch irgendwas einstellen?

Vielen Dank schon mal für eure Antworten

05.07.2008 - 12:42 Uhr

Das hier geht natürlich schon:


 public class Test<T>
    {
        public T this[int index] 
        {
            get
            {
                return default(T);
            }
            set
            {

            }

        }

    }

02.07.2008 - 13:04 Uhr

Hm du könntest auch das ASP.NET Membership System verwenden. Das bietet schon eine fertig Benutzer und Rollen Verwaltung. (Kann man auch für normale Windows Forms Anwendungen verwenden). Einfach mal danach googeln

01.07.2008 - 10:45 Uhr

Aber es ist zumindest sehr ungünstig und daher nicht zu empfehlen. Da man den Controller neuschreiben oder zumindest ändern muss, wenn das das (G)UI austauscht wird, sollte er so einfach wie möglich sein und so wenig wie möglich Logik enthalten

Die View kann bei mir nur über ein Interface auf den Controller zugreifen. Es ist also kein Problem den Controller einfach auszutauschen. Der Controller kann bei mir von verschiedenen Views verwendet werden.
Hier nochmal ein Beispiel:


    public partial class CustomerView: Form, ICustomerView {

        public ICustomerPresenter Presenter {
            get;
            set;
        }


        [ObservableUpdate]
        public void Update(ICustomerModel observable, ObservableEventArgs args) {
            //...
        }




        private void AddCustomerButton_Click(object sender, EventArgs e) {
            Presenter.AddCustomer(this.CustomerIdTextBox.Text, this.CustomerNameTextBox.Text);
        }
    }
30.06.2008 - 09:43 Uhr

Diesen Ansatz halte ich ehrlich gesagt für falsch. Ein Controller ist dazu da, dem Model Anweisungen zu geben, was es machen soll.

In meinem Fall sieht das so aus, dass das Model öffentliche parameterlose(!) Methoden zur Steuerung bereitstellt, die der Controller dann aufruft.

Das hört sich nicht schlecht an. Allerdings glaube ich nicht, das es hierbei ein richtig oder falsch gibt. Bei den Artikeln die man zu der Thematik findet
ist meistens nicht klar definiert wo sich die Business Logik der Anwendung befindet
bzw. habe ich es so interpretiert, diese in den Controller zu legen. Falls jemand gute Artikel zu dem Thema kennt. Immer her damit 🙂

Die Kommunikation zwischen View und Model stelle ich durch Events dar, die vom Model bereitgestellt werden und der View abboniert. Als Reaktion auf ein Event von einem Model holt sich der View dann z.B. die entsprechenden Daten aus dem Model. Das mache ich genauso...

30.06.2008 - 09:00 Uhr

Für einzelne DLLs kann man keine eigenständigen .config Dateien verwenden.
Hatte vor ein paar Wochen das gleiche Problem.
Es gibt nur eine App.config für die gesamte Anwendung aber es ist nicht möglich für einzelne DLLs seperate App.configs zu verwenden.
Falls du wirklich eigene Konfigurationsdateien benötigst, würde ich mit XML Serialisierung arbeiten.

25.06.2008 - 13:34 Uhr

Hi, ich habe dein Problem mal versucht mit Linq zu lösen,
ob dies schneller ist, weiß ich jedoch nicht.
Vielleicht kannst du's ja mal testen und bescheid geben

   
            Dictionary<int, double> dict1 = new Dictionary<int, double>();
            dict1[0] = 12.1;
            dict1[2] = 13.1;
            // Example for value 1
            double v1 = 2.0;
            // Example for Dictionary 2
            Dictionary<int, double> dict2 = new Dictionary<int, double>();
            dict2[2] = 4.9;
            dict2[6] = -11.8;
            // Example for value 2
            double v2 = -1.0;
            // Init dict 3
            Dictionary<int, double> dict3 = new Dictionary<int, double>();
            // Merge Dictionary

            IEnumerable<KeyValuePair<int, double>> result =
                from id1 in dict1.Keys
                select dict2.ContainsKey(id1) ? new KeyValuePair<int, double>(id1, dict1[id1] * v1 + dict2[id1] * v2) :
                                                 new KeyValuePair<int, double>(id1, dict1[id1] * v1);

            dict3.Concat(result);

            result =
                from id2 in dict2.Keys
                where !dict3.ContainsKey(id2)
                select new KeyValuePair<int, double>(id2, dict2[id2] * v2);

            dict3.Concat(result);         

25.06.2008 - 10:21 Uhr

Ich finde zu dem Thema die Artikel von Martin Fowler ganz interessant

http://www.martinfowler.com/eaaDev/uiArchs.html

Man kann das MVC Pattern natürlich auf verschiedene Art und Weise implementieren.
Wo sich die Business Logik befindet ist tatsächlich umstritten (Model vs. Controller).

dann programmierst du aber daten- aber nicht objektorientiert.

Dass sich im Model die Daten befinden die im View dargestellt werden war schon bei SmallTalk so und SmallTalk ist die Objektorientierte Programmiersprache schlechthin und alle GUI Controlls wurden hier zum ersten mal nach dem MVC Patter implementiert.

Ich bin mit meiner Vorgehensweise bisher eigentlich immer ganz gut gefahren, lasse mich aber auch eines besseren belehren. Deshalb würde ich mich freuen wenn noch mehr Leute Ihre Erfahrungen und Interpretationen zu MVC posten würden.

Unabhängig davon kostet die Flexibilität natürlich auch. Man muss also auch aufpassen, dass man es nicht übertreibt. Eine gute Struktur ist wichtig. Aber zuviel Flexibilität ist (fast) genauso schlecht wie zu wenig.

Dem kann ich nur zustimmen, zumal manchmal eine zu hohe Flexibilität nicht vom zur Verfügung stehenden Budget gedeckt wird.

24.06.2008 - 17:18 Uhr

Das kommt darauf an wie flexibel die zu erstellende Anwendung sein soll.
Wenn es grundsätzlich vorgesehen ist, die Controller Logik für Windows Forms, WPF oder WebForms oder irgendeine andere View-Technologie zu verwenden,
muss man sich für die Controller Komponente etwas einfallen lassen um diese von der Form Klasse zu trennen.

Das Model enthällt normalerweise nur die Daten der View und je nach dem wie man es implementiert die Logik zum abrufen der Daten.
Hier nochmal meine Interpretation:
View:
nur Darstellungs und GUI Logik z.B. Farbe eines Items ändern, wenn Wert X=5
Model:
Daten die in der View dargestellt werden.

Controller:
Ausführung der Business Logik z.B. AddCustomer(Customer customer)

Die Synchronisierung von Model und View kann auf verschiedene Art und Weise durchgeführt werden z.B. Observer Pattern, DataBinding

bei
MVP hat das Model überhaupt keine Verbindung mehr zur View und die Synchroniserung der Daten läuft über den Presenter

Wenn man die Komponenten sauber voneinander trennt hat man die größtmögliche Flexibilität und kann jederzeit Model View oder Controller durch eine andere Implementierung austauschen.

24.06.2008 - 15:45 Uhr

Da ich mich mit dem Thema schon des öfteren intensiv auseinandergesetzt habe, möchte ich jetzt auch mal meinen Senf dazugeben:

Das ist einer der Gründe, warum es unter Windows Forms nicht sinnvoll ist, View und Controller zu trennen.

Dem kann ich nicht direkt zustimmen. Es kommt eben auch darauf an wie man den Begriff Controller definiert. Ich sehe den Controller als die Komponente in der sich die tatsächliche Business Logik befindet z.B. sowas in der Art: AddCustomer(Customer customer). Von diesem Gesichtspunkt aus macht es sehr wohl Sinn hierfür
einen eigenständigen Controller zu haben um Logik und Design zu trennen.
Man kann das ganze dann noch weiter treiben und bei den Controller Methoden
verschieden aufrufen z.B.

AddCustomer(Customer customer)
{
      ......
      ICustomerService.AddCustomer(customer)
      .....
      //Model aktualisieren
      //View aktualisieren   
}

Die View enthällt bei mir nur die EventHandler in denen dann Methoden vom Controller aufgerufen werden.

Ich bin jetzt jedoch dazu übergegangen auf das MVP Pattern umzusteigen, da ich denke dass dies für die heutigen Anwendungen besser geeignet ist. Hier hat man ebenfalls eine klare Trennung zwischen View und Controller (hier Presenter).

Der Presenter hat hierbei über ein definiertes Interface Zugang zur View. Ist aber durch das Interface von der konkreten Implementierung abstrahiert. Bei MVP ist aber im Normalfall keine Verbindung von der View zum Model.
Die komplette Kommunikation findet über den Presenter statt. Dies vereinfacht die Implementierung gegenüber dem normalen MVC.

30.04.2008 - 09:27 Uhr

Hi, falls ihr einen vorhanden ConnectionString zur Laufzeit verändern möchtet,
bietet sich hierzu die Klasse SqlConnectionStringBuilder an.

28.03.2008 - 10:30 Uhr

Hilft wohl nichts, werde mir jetzt selbst etwas mit Hilfe von NVelocity bauen, mit den genannten Tools kann ich nicht wirklich etwas anfangen - bzw. sind meine Anforderungen zu speziell z.B. 100 inserts mit Datumswerten welche auf n Monate verteilt sind. Falls doch noch jemand eine Idee hat, wär ich sehr dankbar.

20.03.2008 - 11:41 Uhr

Sehr interessant, werde das ganze gleich mal in meinen einfachen Tabellen Mapper integrieren. Damit dürfte ich Performanzmäßig noch einiges herausholen können 🙂.

Die DynamicMethod Variante habe ich mir auch schon angesehen.
Ich befürchte auch, dass diese Vorgehensweise langsamer ist.

19.03.2008 - 18:48 Uhr

Ok, habs jetzt selbst rausgefunden, hatte die falsche Projektvorlage...
Also mal schaun ob ich damit etwas erreichen kann....

19.03.2008 - 18:32 Uhr

Habe bei mir bereits die Professional Version vom VS2008 installiert.
Habe dann nachträglich die Team Suite darüber installiert, konnte aber keine
Funktion zum Testdaten generieren finden. Wo befindet sich denn das ganze im Visual Studio?

Hoffe das darüber installieren hat funktioniert, ansonsten müsste ich meine aktuelle Umgebung neu einrichten 😦

19.03.2008 - 13:21 Uhr

schau ich mir gleich mal an - danke

19.03.2008 - 13:13 Uhr

Man sollte imho auch in die Auswahl ob Struct oder Class einfließen lassen,
dass die größe des zur Verfügung stehenden Stacks begrenzt ist.

Die gewünschte Stack Größe kann man z.B. beim erzeugen eines neuen Threads mit angeben.

Grundsätzlich denke ich dass man structs am besten für folgende Szenarien verwendet:

  • kleine eigene Datentypen
  • man benötigt keine Vererbung
  • Referenztyp Verhalten ist nicht notwendig
  • Es werden keine rießigen Datenmengen erwartet

bei einer Klasse sieht es dann entsprechend anders aus.

Datenbankentitäten würd ich z.B. als Klasse modelieren,
weil die zu verarbeitende und weiterzugende Datenmenge rießig sein kann.
(muss natürlich nicht sein, wenn man immer nur kleine Teilmengen benötigt)

Beispiel:
Entität Person wird auf den DotNet Typ Person gemappt

  • davon werden z.B. 100 Objekte von diesen Typ erzeugt
    Diese Objekte werden durch eine Methode z.B. MapToList(...) in einer Collection gespeichert und von dieser Methode zurückgeliefert.

Ist Person als struct implementiert, müssen alle 100 Objekte kopiert werden,
bei Klassen muss nur der Verweis zurückgegeben werden.

19.03.2008 - 12:03 Uhr

Wenn ihr ein gutes kommerzielles Produkt kennt, dann einfach mal posten.
Anschaun kann man sich's ja mal vielleicht wird es ja von meiner Firma bezahlt,
wenn es sein Geld wert ist 🙂

19.03.2008 - 11:04 Uhr

Hi denke auch, das es nicht anders geht,
schreib dir einfach etwas in der Art:


public static T IsNull<T>(object sourceValue,T nullReplace)
{
	if(sourceValue is DBNull)
	{
		return nullReplace;
	}
	return (T)sourceValue;
}

//mit C# 3.0 brauchst du dann auch den generischen Typ nicht mehr mit zu übergeben:
object dbVal = 10;
int intDbVal = IsNull(dbVal, 0);
//intDbVal = 10;
			
			
dbVal = DBNull.Value;
intDbVal = IsNull(dbVal, 0);
//intDbVal = 0

Schade, dass man beim DataAdapter nicht einstellen kann,
dass er Datenbank Nullwerte z.B. als .NET Null Werte zurückgeben soll - oder geht das doch irgendwie?

Würde ja auch bei einfachen Typen dank der Nullable Neuerung in C# 2.0 funktionieren...

19.03.2008 - 10:43 Uhr

verwendetes Datenbanksystem: SQL-Server 2005
Hi, ich bin auf der Suche nach einem guten kostenlosen Tool
mit dem man sich Testdaten für eine SQL-Server Datenbank erzeugen kann.

Das Tool sollte dabei Insert Statements generieren.
Außerdem sollte es möglich sein Templates für die Inserts zu definieren.
Suche etwas ähnliches wie NVelocity oder iCodeGenerator.
Kennt von euch jemand etwas derartiges?

Über ein paar Tips oder Erfahrungen mit dem ein oder anderen Tool wäre ich sehr dankbar.

18.03.2008 - 16:28 Uhr

Hi ich habe jetzt noch eine sehr interessante Möglichkeit gefunden wie man sich mit den neuen Sprachfeatures von C# 3.0 einen einfachen Mapper bauen kann - dachte ich poste das ganze mal hier:


public static List<T> MapToList<T>(DbDataReader dbDataReader, T Prototype) {
			List<T> ReturnList = new List<T>();
			Type EntityType = typeof(T);
			ConstructorInfo[] Constructors = EntityType.GetConstructors();
			ParameterInfo[] ConPara = Constructors[0].GetParameters();

			
			int columnCount = dbDataReader.FieldCount;
			while (dbDataReader.Read()) {
				object[] o = new object[Constructors[0].GetParameters().Length];
				
				object[] dataRow = new object[columnCount];
				dbDataReader.GetValues(dataRow);
				ConvertDbNullToNull(dataRow);
				T NewEntity = (T)Constructors[0].Invoke(dataRow);
				ReturnList.Add(NewEntity);
			}

			return ReturnList;
		}

private static void ConvertDbNullToNull(object[] values) {
			for (int i = 0; i < values.Length; i++) {
				if (values[i] is DBNull) {
					values[i] = null;
				}
			}
		}

damit kann man dann z.B. folgendes machen:


DbDataReader dataReader = ...

var Prototype = new { Id = 0, Name = ""};
var EntityList = MapToList(dataReader, Prototype);


Sehr nützlich wenn mann nur mal eben ein paar Daten abfragen möchte

14.03.2008 - 15:25 Uhr

Hallo,
ich habe jetzt mal selbst recherchiert und habe jetzt eine Klasse bei CodeProject gefunden Fast Dynamic Property Access mit der meine Routine nochmals um einiges schneller läuft.

Mit der Klasse PropertyAccessor kann man sich zur Laufzeit Code generieren mit dem dann der Zugriff auf die Properties erfolgt (-> Beitrag von OnlineGurke)
ich bin echt beeindruckt wie stark sich die Beschleunigung auswirkt:
Tabelle mit 8 Spalten und 356.000 Zeilen
mit DbDataAdapter.Fill(DataTable) ca 3,6 Sekunden
mit meiner Routine und Standard Reflection ca 18 Sekunden!!!
mit Fast Property Access ca 4 Sekunden

Wow!!!
Danke euch allen habe jetzt meine Methode fertig 🙂
Bei Interess kann ich gerne mal den kompletten Quellcode posten.

13.03.2008 - 13:21 Uhr

Hallo,
erstmal wieso hast du überhaupt Umlaute in deinen Spaltennamen
zeugt nicht unbedingt von einer klaren/guten Namensstruktur.

Du kannst jedenfalls in den einzelnen Spalten deines GridViews (--> Hilfe)
die Namen der Spalten so wie so angezeigt werden sollen selbt konfigurieren.

12.03.2008 - 13:13 Uhr

Nicht ganz, mit MAX bekommst du nur den maximalen Wert einer Spalte
z.B. SELECT MAX(ID) FROM MyTable
wenn du jetzt aber den Eintrag aus der Tabelle MyTable
holen möchtest benötigst du einen Subselect:

z.B. SELECT Id, Type FROM MyTable
WHERE Id = (SELECT MAX(ID) FROM MyTable)

12.03.2008 - 08:38 Uhr

Onlinegurke könntest du mir bitte noch etwas genauer erklären wie du das mit DynamicMethod gemeint hast. Ich habe im Bereich System.Reflection.Emit noch keine Erfahrung. Soweit ich das jetzt aber beim durchlesen der Hilfe zu DynamicMethod
verstanden habe, kann man sich damit neue Methoden zur Laufzeit erzeugen.
Inwieweit hilft mir dies den Zugriff auf den PropertySetter zu beschleunigen?

11.03.2008 - 18:27 Uhr

Hab das Problem jetzt selbst gelöst.


public static List<T> MapToList<T,P>(DbDataReader dbDataReader, int capacity) where T: new()
																					  where P : T, new()
		{
			List<T> ReturnList = new List<T>(capacity);
			Type EntityType = typeof(T);
			IDictionary<string, PropertyInfo> EntityProperties = 
							TypeHelper.GetPropertiesAsDictionary<T>();
			PropertyInfo[] PropertyInfoArr = EntityType.GetProperties();
			int j=0;
			dbDataReader.GetSchemaTable().WriteXml("C:\\test.xml");
			while (dbDataReader.Read()) {
				T NewEntity = new P();
				//Console.WriteLine("Row: " + j++);
				#region map simple types
				
				for(int i=0;i< dbDataReader.FieldCount;i++)
				{
					object RowValue = null;
					try
					{
						RowValue = dbDataReader.GetValue(i);
						if (!(RowValue is DBNull)) {
							if (RowValue.GetType() !=
								EntityProperties[dbDataReader.GetName(i)].PropertyType) {
								//handle different types
								Type PropertyType =
									EntityProperties[dbDataReader.GetName(i)].PropertyType;
								//if the property type is nullable - we need the underlying type
								if (Nullable.GetUnderlyingType(PropertyType) != null) {								
									PropertyType = Nullable.GetUnderlyingType(PropertyType);
								}

								RowValue = TypeHelper.ConvertType(RowValue, PropertyType);
								
							}
							EntityProperties[dbDataReader.GetName(i)].
										SetValue(NewEntity, RowValue, null);
						}
					}catch(Exception)
					{
						continue;
					}
				}
				#endregion
				ReturnList.Add(NewEntity);
			}

			return ReturnList;
		}


public static object ConvertType(object source, Type targetType) {
			if(targetType == typeof(bool))
			{
				return Convert.ToBoolean(source);
			} else if (targetType == typeof(int)) {
				return Convert.ToInt32(source);
			} else if (targetType == typeof(long)) {
				return Convert.ToInt64(source);
			} else if (targetType == typeof(short)) {
				return Convert.ToInt16(source);
			} else if (targetType == typeof(byte)) {
				return Convert.ToByte(source);
			} else if (targetType == typeof(ulong)) {
				return Convert.ToUInt64(source);
			}
			return source;
		}


Die Bremse war anscheinend die Methode
Convert.ChangeType

Hab die Typänderung jetzt durch eine eigene Routine ersetzt.

Vielleicht hat aber jemand noch eine Idee wie man eine solche Typkonvertierung noch schöner/performanter hinbekommt.

Bin jetzt aber mit der Performanz eigentlich schon zufrieden.
Der Unterschied war extrem. Vorher lag die Reaktionszeit bei einer Tabelle mit
zehn Spalten und 8000 Zeilen bei ca. 1 Minute jetzt
dauerts nur noch eine Sekunden 🙂

11.03.2008 - 15:41 Uhr

verwendetes Datenbanksystem: Datenbankunabhängig - Referenzsystem SQL Server 2005

Ich bin gerade dabei mir eine kleine Hilfsroutine zu schreiben, welche anhand
der Property Namen meiner Entität aus einem DbDataReader die Ergebnisse ausliest und daraufhin eine generische Liste füllt. Natürlich müssen die Propertynamen bei meiner Methode mit den Spalten der Ergebnistabelle übereinstimmen.
Funktioniert soweit auch ganz gut. Allerding ist die Performanz nicht unbedingt sonderlich zufriedenstellend.

Im direkten Vergleich schneidet das befüllen einer DataTable durch einen DbDataAdapter um einiges besser ab.


public static List<T> MapToList<T,P>(DbDataReader dbDataReader, int capacity) where T: new()
																					  where P : T, new()
		{
			List<T> ReturnList = new List<T>(capacity);
			PropertyInfo[] PropertyInfoArr =
								typeof(T).GetProperties();
			while (dbDataReader.Read()) {
				T NewEntity = new P();
				
				#region map simple types
				foreach (PropertyInfo propInfo in PropertyInfoArr) {
					object RowValue = null;
					Type PropertyType = propInfo.PropertyType;

					try {
						RowValue = dbDataReader[propInfo.Name];
						if(!(RowValue is DBNull))
						{
							if (RowValue.GetType() != PropertyType &&
								!PropertyType.IsEnum &&
								!PropertyType.IsAssignableFrom(RowValue.GetType())) {
								if (TypeHelper.IsNullableType(PropertyType)) {
									RowValue = Convert.ChangeType(RowValue, Nullable.GetUnderlyingType(PropertyType));
								} else {
									RowValue = Convert.ChangeType(RowValue, PropertyType);
								}
							} 
							propInfo.SetValue(NewEntity, RowValue, null);							
						}						
					} catch (IndexOutOfRangeException) {
						continue;
					} 
				}
				#endregion
				ReturnList.Add(NewEntity);
			}

			return ReturnList;
		}

Hat von euch vielleicht noch jemand Ideen wie man das ganze noch optimieren könnte. Ich schau mir gerade den Quellcode der DbDataAdapter.Fill Methoden genauer an. Ist aber doch sehr schwierig anhand des Quellcodes darauf zu schließen wie der Mechanismus funktioniert.

Natürlich könnte ich einen bestehenden OR-Mapper verwenden, das ist aber gar nicht meine Intention. Ich möchte nur eine kleine Methode welche ich bei Bedarf schnell einsetzen kann.

03.03.2008 - 10:54 Uhr

Für die Implementierung des Datenzugriffs gibt es grundsätzlich verschieden Lösungsstrategien.

Dabei kann auf verschieden erprobte Patterns zurückgegriffen werden.
Grundsätzlich sollte eine Anwendung in verschiedene Schichten aufgeteilt werden.

  1. Layer: User Interface
  2. Layer: Business Logik
  3. Layer: Datenzugriffslogik

Wenn du nur eine einfache kleine Anwendung programmierst, kannst du auch
alles in einer Schicht implementieren. Ich halte dies persönlich aber für keine gute Idee...
Wenn du den Datenzugriff mit der User Interface Logik mischst, hast zu
den Nachteil das du z.B. eine riesige monolithische WinForm Klasse hast.
Was wiederum zu einem sehr schlechten Wartungsergebnis führt.

Bei den Patterns für Datenzugriff wird häufig das DAO Pattern oder das Active Record
Pattern eingesetzt. Eine genaue Erklärung der Pattern würde an dieser Stelle zu weit führen.

Man kann auch je nach dem wie aufwändig das Projekt ist die Verwendung von OR-Mappern in erwägung ziehen. NHibernate finde ich für .NET richtig Klasse.