ich habe eine Liste mit Dictionaries mit den Keys "Column_1", "Column_2", "Column_3"
Außerdem eine List in der die Keys stehen nach dem ich das Dictionary gruppieren möchte.
List<string> GroupColumns = { "Column_1", "Column_2" };
Ich möchte nun das Dictionary nach den GroupColumns gruppieren und finde es schwierig das umzusetzen.
List<Dictionary<string, string>> data = new List<Dictionary<string, string>>();
Dictionary<string, string> d1 = new Dictionary<string, string>();
d1.Add("Column_1", "A");
d1.Add("Column_2", "B");
d1.Add("Column_3", "C");
Dictionary<string, string> d2 = new Dictionary<string, string>();
d2.Add("Column_1", "E");
d2.Add("Column_2", "B");
d2.Add("Column_3", "C");
Dictionary<string, string> d3 = new Dictionary<string, string>();
d3.Add("Column_1", "G");
d3.Add("Column_2", "B");
d3.Add("Column_3", "C");
data.Add(d1);
data.Add(d2);
data.Add(d3);
List<string> groupColumns = new List<string>{ "Column_1", "Column_2" };
var grouped = data.GroupBy(x => x[groupColumn[0]]); // nach einem column funktioniert
// -> Ergebnis
// A
// E
// Ich möchte aber nun nach den Columns in der Liste gruppieren, hat jemand eine Idee?
// -> Ich möchte folgendes Ergebnis:
// A B
// E B
// G B
Ich möchte aber nun nach den Columns in der Liste gruppieren, hat jemand eine Idee?
ich hänge gerade bei einem Problem etwas in der Luft und hoffe ihr könnt mir helfen.
// Eine Liste mit vielen Zeilen die wiederum pro Zeile mehrere Spalten enthält
List<List<string>> lines = new List<List<string>>();
// In der Liste steht z.B.
// 1. Zeile: A, B, C
// 2. Zeile: A, B, D
// 3. Zeile: A, C, E
// Wieviel Spalten eine Zeile hat ist unbekannt.
// Ich möchte nun gruppieren das am ende die folgende Struktur heraus kommt:
//
// A, B, C
// , , D
// A, C, E
// Also quasi eine Gruppierung nach einer unbekannten Anzahl an spalten, damit Werte nicht doppelt übereinander stehen.
Hat jemand eine Idee?
Noch ein Beispiel:
Welt, Europa, Deutschland
Welt, Europa, England,
Welt, Europa, Frankreich
wird in der Ausgabe zu
Welt, Europa, Deutschland
England
Frankreich
Vielleicht bietet sich auch eine andere Struktur an.
um Daten zu validieren durchlaufe ich eine Tabelle spaltenweise in einer for-Schleife.
Zu jeder Spalte sind feste Regeln (manche optional) definiert:
- Datentyp
- MaxLength
- Whitelist (Daten die in der Spalte stehen dürfen)
Wie schon gesagt, durchlaufe ich die Spaltenwerte in einer for-schleife, prüfe in if Bedinungen die Regeln und teste anschließend auf DatenTyp, Maxlength usw.
Meine Frage ist nun: Gibt es dafür einen besseren Weg? Lässt sich beispielsweise eine ganze Liste aus String Werten performant auf Integer Werte prüfen?
Ich bin für jeden PerformanceTip dankbar.
Anbei auch der Code.
// Spaltenweise
for (int i = 0; i < rules.Count; i++)
{
ValidationRules rule = rules[i];
ExcelValidatorLog log = new ExcelValidatorLog("Errors of column: " + rule.headerName + Environment.NewLine);
int excelColIndex = i + 1;
for (int j = 2; j < excelData.GetLength(0); j++)
{
string value = excelData[j, excelColIndex] == null ? null : excelData[j, excelColIndex].ToString();
if (string.IsNullOrEmpty(value) && rule.nullable == 0)
{
// Wert darf nicht null sein
log.Add(j, value, "Value is not allowed to be null or empty.");
}
switch (rule.dataType)
{
case 0:
// int
if (rule.nullable == 1 && value == null)
break;
int outInt = -1;
if (!int.TryParse(value, out outInt))
{
log.Add(j, value, "Value must be number.");
}
break;
case 1:
if (rule.nullable == 1 && value == null)
break;
// String - Größe prüfen
if (value.Length > rule.length)
{
log.Add(j, value, "Value length restriction of " + rule.length + " exceeded.");
}
// whitelist test
if (!string.IsNullOrEmpty(rule.whitelist))
{
string[] whiteListValues = rule.whitelist.Split(';');
if (!whiteListValues.Contains(value))
{
log.Add(j, value, "Value must match a whitelist value.");
}
}
break;
case 2:
// Iso Länder Code
if (!isoCodeList.Contains(value))
{
log.Add(j, value, "Value is no isocode.");
}
break;
case 3:
// Datetime
if (string.IsNullOrEmpty(value) && rule.nullable == 1)
break; // its fine
try
{
double d = double.Parse(value);
DateTime conv = DateTime.FromOADate(d);
}
catch
{
log.Add(j, value, "Value must be a Datetime.");
}
break;
case 4:
float f = 1.0f;
if (!float.TryParse(value, out f))
{
log.Add(j, value, "Value must be a float value.");
}
break;
case 5:
// int
if (rule.nullable == 1 && value == null)
break;
long outLong = -1;
if (!long.TryParse(value, out outLong))
{
log.Add(j, value, "Value must be number.");
}
break;
case 6:
// Datetime
if (string.IsNullOrEmpty(value) && rule.nullable == 1)
break; // its fine
try
{
double d = double.Parse(value);
DateTime conv = DateTime.FromOADate(d);
if (conv > DateTime.Now)
{
// Wert darf nicht in der Zukunft liegen
log.Add(j, value, "Date has to be in the past, but it is in the future.");
}
}
catch
{
log.Add(j, value, "Value must be a Datetime.");
}
break;
}
if (rule.primaryKey.Value && excelColIndex == 1)
{
primaryKeys.Add(value);
}
else if(rule.primaryKey.Value)
{
primaryKeys[j-2] += value;
}
}
}
EPPlus habe ich auch versucht, aber bei manchen Dateien einen Interop Fehler bekommen. Das war für mich nicht debugbar und deshalb habe ich auf die Library verzichtet.
Open XML SDK schaue ich mir mal an, vielen Dank
Weiß denn jemand worauf es an kommt das eine Datei schnell eingelesen werden kann, oder welche Library die schnellste für das reine lesen ist?
30-40 Sekunden für eine Datei die schon im Speicher liegt finde ich etwas zu langsam.
hat jemand Erfahrung, was die schnellste Möglichkeit ist Excel Dateien in C# einzulesen und dann in einem gut zu bearbeiteten Objekt (z.B. DataTable) verfügbar zu haben?
Eine 24 MB Excel Datei benötigt bei mir vom Umwandeln des Streams in eine DataTable ca 30-40 Sekunden.
D.h. die Datei liegt schon vollständig als Stream vor und benötigt weitere 30-40 Sekunden bis Sie zu bearbeiten ist.
Ich brauche nur die Werte da raus (Formeln sind nicht relevant) und möchte wenn möglich kein echtes Excel im Hintergrund öffnen.
vielen Dank dafür. Das war mir nicht klar. Das probiere ich auf jeden Fall aus.
Aber eine Frage dazu (Interesse halber):
Spielt es noch eine Rolle wie ich die Excel Datei lese wenn ich sie bereits in meiner DataTable habe? Kann die Art und Weise irgendwie einen Einfluss darauf haben, wenn ich da durch iteriere?
Ich habe bisher noch mit keinem Profiler gearbeitet. Habe Visual Studio 2013. Ich versuche mal, ob ich das irgendwie hinbekomme. Gibts da einen bestimmten den ich nutzten sollte?
Sorry die wichtige Information habe ich vergessen.
Worksheet ist ein DataTable
Ich muss die Dateien lesen, validieren und dann in eine SQL Datenbank packen. D.h. ich muss diese Dateien Menge anDaten lesen (was letztendlich auch nur 45 MB sind)
Mit dem Profiler versuche ich mal. Aber die Problematik dreht sich wirklich nur um diese Forschleife.
ich hoffe ich habe den richtigen Bereich für meine Frage gefunden.
Ich habe eine DataTable (workSheet) die ich wie folgt zu IEnumerable<DataRow> umwandle:
IEnumerable<DataRow> rows = from DataRow row in workSheet.Rows
select row;
Durch diese Zeilen iteriere ich dann und hole mir aus jeder Zeile die Werte die ich benötigte und schreibe diese in ein Dictionary.
for (int i = 1; i < rows.Count(); i++)
{
DataRow row = rows.ElementAt(i);
for (int j = 0; j < rules.Count; ++j)
{
dataDict[rules[j].headerName].Add(row.ItemArray[j].ToString());
}
}
Die Datatable hat ca. 100 000 Zeilen. Von jeder Zeile werden je 7 Werte in unterschiedliche Dictionary's geschrieben. (Pro Spalte 1 Dictionary)
D.h. das diese Schleife ca. 700 000 mal durchlaufen wird.
Wenn ich diese laufen lasse und nach 10 Minuten einen Breakpoint setze ist die Schleife gerade mal bei Datensatz 5000.
Ich habe etwas gegoogelt und ganz andere zeitliche Zahlen gefunden.
Was läuft da falsch? Was ist so unglaublich unperformant?
Ein paar Zusatzinformation:
- Die Datatable wurde aus einem Excel File erstellt, ist zu diesem Zeitpunkt aber schon komplett vorhanden.
- Das umwandeln der Datatable in IEnumerable ist hier unbeachtet (das würde ich noch ändern)
- Es geht hier nur darum die spalten in einzelne Listen zu schreiben. Warum dauert das so lange?
- Es handelt sich um eine MVC 4 Anwendung
- Es läuft in einem Thread
ich hatte erst überlegt ob mein Thema nicht zu Office Technologien gehört, war mir dann aber nicht so sicher.
Ich habe eine ASP.net Anwendung der in einem Order ptox Dateien zur Verfügung stehen. Was ich brauche ist eine Möglichkeit von jeder MasterSlide eines Powerpoint Dokuments ein Image zu speichern.
Ich habe für normale ppt Dateien schon eine Lösung gefunden. Doch wie auf die Masterslides?
Hat da jemand einen Anhaltspunkt für mich?
using Microsoft.Office.Core;
using Microsoft.Office.Interop.PowerPoint;
public static void CreateSlideImage(string pptFilePath, int slide, string exportPath)
{
Application pptApplication = new Application();
Presentation pptPresentation = pptApplication.Presentations.Open(pptFilePath, MsoTriState.msoTrue, MsoTriState.msoTrue, MsoTriState.msoFalse);
Console.WriteLine(pptPresentation.HandoutMaster.Shapes);
pptPresentation.Slides[slide].Export(exportPath, "png", 320, 240);
}
War wirklich sehr hilfreich - vielen Dank. Natürlich gibt mir die Aussage das OnDisconnect nur in 95% der Fälle geworfen wird etwas zu denken.
Irgendwelche Ideen wie man eventuelle Fehlerquoten abfängt oder korrigiert?
Gibt es die Möglichkeit eine Art Backgroundworker laufen zu lassen der unabhängig von einem Webseitenaufruf läuft? In diesem könnte man auf alte Sessions prüfen und ggf. auch ob ein Client noch da ist?
ich habe in meiner Asp.net Anwendung SignalR laufen und speichere die clientIds in einer statischen Liste.
Wie kann ich diese clientIds nun auf meine internen User mappen?
In meinen Controllern habe ich keinen zugriff auf die clientId bzw. connectionId des users der diesen Aufruf durchführt.
Fallbeispiel:
Webseitenaufrufe -> Controller erstellt Datensatz mit clientId in der Datenbank (die brauch ich)
User schließt die Webseite -> SignalR erkennt das und löscht den Datensatz mit der clientId aus der Datenbank
Ich habe viel recherchiert und nur Fallbeispiele gefunden wo man die userId von SignalR in eine statische Liste schreibt. Leider fehlt mir dabei komplett die zuordnung zu meinem AKTUELLEN User.
Danke für jeden Hinweis
PS: Ich versteh auch irgendwie nicht ganz warum SingalR nicht problemlos sessionbasiert laufen kann.. dann wär das so schön einfach... :(
ich kann mir vorstellen das eine spezifische Frage zu HBCI etwas zu schwer zu beantworten wäre, und stelle diese deshalb etwas allgemeiner.
Bei HBCI gibt es das Datenformat Binär.
Dieses wird in die Textnachrichten die zwischen Kunde und Kreditinstitut versendet werden folgendermaßen eingestellt.
@Länge-Bytes@Binäre-Daten
Die Nachrichten an einen Bankserver werden base64 kodiert und dann per SSL versendet.
Ich frage mich nun, wie die Binären Daten in C# in die Nachricht eingestellt werden?
Wandel ich die "Strings" in ein Byte-Array um und setze sie einfach in den String ein? Oder als eine Folge von 1en und 0en?
Wie könntet Ihr euch vorstellen funktioniert das in c#? Die Spezifikation gibt mir die Antwort leider nicht.
Den String in Bytes zu konvertieren und mitzugschicken, führt zu einem 400er Returncode.
Du kannst die Datatable mit einem DataColumn vom Datentyp Byte Array erstellen.
Bindest du die Datatable dann an das DataGridView wird dafür automatisch ein entsprechender Column Typ verwendet.
string picturePath = "bilder/bild.jpg";
DataTable dataTable = new DataTable();
DataColumn dcArNr = new DataColumn("Artikelnummer", typeof(string));
DataColumn dcBild2 = new DataColumn("Bildpfad", typeof(string));
DataColumn dcBild = new DataColumn("Bild", typeof(Byte[]));
dataTable.Columns.Add(dcArNr);
dataTable.Columns.Add(dcBild2);
dataTable.Columns.Add(dcBild);
DataRow row = dataTable.NewRow();
row.SetField<string>(dcArNr, "123456");
row.SetField<string>(dcBild2, picturePath);
// in der datatable muss das Bild dann als Byte Array vorliegen
// z.B. so
MemoryStream m = new MemoryStream();
Image.FromFile(picturePath).Save(m, System.Drawing.Imaging.ImageFormat.Jpeg);
row.SetField<Byte[]>(dcBild, m.ToArray());
dataTable.Rows.Add(row);
dataGridView.DataSource = dataTable;
Da mir der ContentType der E-mail ja sagt er sei ein ISO-8859-1, wandel ich
den Text in ein ByteArray und versuche anschließend das Bytearray von Iso zu UTF8 zu konvertieren.
Leider ohne erfolg, die umlaute werden nach wie vor nicht angezeigt.
Die HTML E-Mail Daten kommen als iso-8859-1 an. Die Umlaute werden alle nicht richtig angezeigt und ich kriege die Umwandlung in das richtige Format einfach nicht hin.
Zeichensätze machen mir leider schon immer Probleme und ich würde mich freuen wenn mir hier jemand den richtigen Tip geben könnte.
Beim ausführen des von mir geschriebenen Programms auf einem anderen Rechner bekomme ich folgende Meldung:
Fehler
Could not load file or assembly 'System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. Das System kann die angegebene Datei nicht finden.
.Net Framework 4.0 ist installiert -
Woran kann das liegen? Ist bei der .NET installation vll ein Fehler aufgetreten?
Unter Software sehe ich auch die anderen .Net Framewors 2.0, 3.5 und 4.0
ich versuche mich gerade in Linq einzuarbeiten, unter anderem hänge ich gerade an einer Linq Abfrage. Bin aber auch nicht sicher ob das was ich machen möchte wirklich möglich ist.
Ein Änderungserfassungsystem nimmt Änderungen an Angebots- und Stamm- datensätzen auf und speichert diese in eine extra Tabelle.
Die Änderungen vom vorherigen zum neuen Datensatz werden in einer extra Spalte erfasst.
(Soviel nur, damit klar wird worum es geht)
-------------------------------------------------------------
Ziel ist es nun, die Historie eines Datensatzes übersichtlich anzuzeigen.
Damit sofort gesehen werden kann, wann was geändert wurde.
Um das zu lösen wollte ich die Datensätze in einem DataGridView untereinander anzeigen. (nur die geänderten Felder - also werden die Felder die angezeigt werden je nach Datensatz dynamisch erzeugt)
Dabei gibt es Felder mit sehr kurzem Inhalt aber eben auch Felder wie das Memofeld wo sehr viel drin stehen kann. Da das DataGridView mit viel Daten in einer Zelle aber nicht zurecht kommt suche ich nach einer Alternative.
Vielleicht kommt ein ListView ja besser mit vielen Daten in einer Zelle zurecht?
Liegt also eindeutig an der Menge des Textes. Die Zelle ist wohl einfach nicht dafür gemacht soviel Text zu beinhalten.
Hat jemand vielleicht Alternativen? Was könnt ich denn sonst nehmen?
Das ganze dient eigentlich dazu Datensätze zu vergleichen und ein Feld des Datensatzes hat nunmal sehr viele Einträge da es sich um ein Memofeld handelt.