verwendetes Datenbanksystem: IBM DB2 - es geht aber um alle DBMS allgemein
Hallo zusammen,
ich arbeite mich momentan in das ORM "Dapper" ein.
Wir haben hier u.a. ne IBM DB2 und da gibts Tabellen mit 70 und mehr Spalten.
Da habe ich ne kurze Frage zur besten Design-Herangehensweise.
Ist es so, dass die Models immer komplette Tabellen abbilden, oder kann man auch Models erstellen, die z.B. nur einige Spalten aus SQL-Selektionen beinhalten.
Oder man hat Views oder Abfragen mit mehreren Joins über verschiedene Tabellen und möchte die Abfrageergebnisse in einem Model darstellen.
Das macht m.E. nur bei Anwendungen Sinn, die ausschließlich lesend auf die DB zugreifen, sollte aber da funktionieren.
Praktiziert ihr das auch, oder modelt ihr immer konsequent und nachhaltig alle Tabellen in eure Datenmodelle (POCOs)?
Welche Vorteile/Nachteile seht ihr an dieser Vorgehensweise?
ich arbeite in einem Unternehmen (Weniger als 250 PCs, aber mehr als 1 Million $ Jahresumsatz).
Wir sind kein IT oder Software-Unternehmen, sondern fertigen Produkte aus den Bereichen Textil und Wohnen.
Um Prozesse zu vereinfachen plant unsere IT-Abteilung nun zukünftig Tools selbst zu entwickeln.
Dafür soll Visual Studio 2017/2019 und C# auf 2PCs (2 Mann Team) zum Einsatz kommen.
Getestet haben wir mit 2 VS 2017 Community Editionen und würden damit vom Leistungsumfang her zurecht kommen.
Die entwickelten Tools sollen, wie gesagt, nur Abläufe optimieren und keinen direkten Gewinn erzeugen.
Sie werden das Unternehmen nicht verlassen und auch nicht verkauft.
Nutze ich die Software dann kommerziell? Nur indirekt, oder?
Leider würden wir damit wahrscheinlich die Lizenzbestimmungen nicht einhalten, oder wie ist da die Situation?
Ich habe auch schon den Kauf von 2 Professional Editionen in Erwägung gezogen.
Da ist allerdings ein Tausender weg und unserer Geschäftsleitung den Mehrwert, von eigenen Softwares, zu erklären ist immer sehr schwierig, da für die IT hier meist nur geringes Verständnis da ist.
Kurzum, es ist wahscheinlich schwer zu vermitteln!
Deshalb habe ich mal etwas nach Lizenzen gesucht und bin bei EBAY auf spottbillige VS Enterprise 2017/2019 Lizenzschlüssel gestoßen. Nur 10 Euro je Lizenz!!!
Ich kann mir nicht vorstellen, dass diese Lizenzen rechtens sind.
Die eine stammt laut Anbieter aus einer Volumenlizenz und kann aktiviert und uneingeschränkt verwendet, nur nicht registriert werden.
Welche Probleme würden sich aus einer NICHT-Registrierung ergeben?
Ich weiß, dass man hierbei nicht sparen sollte. Muss aber alles abchecken, bevor die Geschäftsleitung angefragt wird und wäre deshalb sehr dankbar für euren Input.
also, ich habe versucht das zu verstehen - muss aber zugeben, dass mir das nicht in den Kopf will.
Meine Startup.cs enthält diese ConfigureServices() Methode:
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
// alle Ressourcendaten werden im Verzeichnis "Resources" gespeichert
services.AddLocalization(opts => { opts.ResourcesPath = "Resources"; });
services.AddMvc()
.AddViewLocalization(opts => { opts.ResourcesPath = "Resources"; })
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.Configure<RequestLocalizationOptions>(opts =>
{
var supportedCultures = new List<CultureInfo>
{
//new CultureInfo("fr-FR"), // Französisch
//new CultureInfo("zh-CN"), // Chinesisch
//...
new CultureInfo("de-DE") // Deutsch
//...
};
// hier wird die Standard Sprache gesetzt
opts.DefaultRequestCulture = new RequestCulture(culture: "de-DE", uiCulture: "de-DE");
//opts.SetDefaultCulture("de-DE");
// zum Formatieren von Zahlen, Datum usw.
opts.SupportedCultures = supportedCultures;
// zum Formatieren des UI
opts.SupportedUICultures = supportedCultures;
});
services.AddDbContext<db_hardware_devContext>(options => options.UseMySQL(Configuration.GetConnectionString("MySqlConnectionString")));
}
Also so in der Art: @Localizer["Nettokaufpreis"] irgendwie.
Ziel soll sein, dass man den Wert mit Komma, also bspw. 77,99 € eingibt, aber intern 77.99 als Value des Input Elements gepostet wird, welchen die Datenbank dann aufnehmen kann.
Macht das Alles der Localizer-Dienst für mich, oder muss ich da controllerseitig noch umwandeln?
ich versuche mich gerade an einer MVC Webanwendng mit ASP.NET Core 2.2.
Die Kommunikation mit der MySql-Datenbank wird mit dem Provider "MySql.Data.EntityFrameworkCore" abgewickelt.
Die Datenbank habe ich mit EF und Database First in Model-Klassen gemappt.
Funktioniert Alles ganz toll, aber:
Ich habe ein Problem mit einem Feld, wo ich datenbankseitig eine Währung speichere.
In MySql habe ich dafür den Datentyp DECIMAL(8,2) mit den Eigenschaften UNSIGNED und DEFAULT(0) für das Feld vereinbart.
Wenn ich jetzt mein z.B.: Edit-View im Browser anschaue, dann wird der Wert aus der DB sauber angezeigt - also z.B.: 81,90 €.
Die Anwendung erkennt also, bei der Ausgabe der Daten, welche Landeswährung auf dem Server eingestellt ist.
Aber, wenn ich den Wert nun ändere, darf ich kein Komma und kein €-Zeichen verwenden, weil er ja einen Zahlenwert (Decimal) verlangt.
Nur, wenn ich z.B.: 90.00 eingebe (was 90,00 € repräsentieren sollte), wird der Wert verarbeitet.
Allerdings speichert es in der Datenbank den Wert 9000.00 was ja auch wieder falsch ist, denn beim nächsten Aufruf wird 9.000,00 € im View angezeigt.
Beim Darstellen der Währung wird ja die richtige Landeswährung herangezogen (GET), warum funktioniert das beim Speichern (POST) nicht ebenso unkompliziert.
Was mache ich falsch?
Muss ich das Feld in der Modelklasse evtl. als String definieren und den Eingabewert, vor dem Speichern in die DB, umwandeln (Klingt aber gefühlt falsch!)?
Ich komme da ohne Hilfe nicht weiter.
Könntet ihr mir bitte weiterhelfen oder einen Tipp geben, wo es Informationen dazu gibt?
Also am DGV liegts wahrscheinlich nicht.
Wenn ich die Liste durchgehe und ausgeben lasse, erhalte ich ebenfalls leere Strings und Nullen bei numerischen Werten.
ich habe das Problem, dass mein DataGridView nach Abfrage auf das DBMS leer bleibt.
Also, die Anzahl der DataGridView Rows stimmt, aber die Werte in den Spalten des DataGridViews bleiben bei Strings leer und bei numerischen Werten 0.
Für mich heißt das, dass die zurückgelieferte List<ErpData> nicht leer ist, weil ja die korrekte Anzahl der Datensätze angezeigt werden, nur die Daten eben nicht.
Ich weiß jetzt nicht, woran das liegt. Könnt ihr mir einen Tipp geben?
namespace Projektname.Models
{
public class ErpData
{
public int Id { get; set; }
public string Auftrag { get; set; }
public string Pos { get; set; }
public string Artikel { get; set; }
public string Material { get; set; }
public string Kategorie { get; set; }
public Single Menge1 { get; set; }
public Single Menge2 { get; set; }
}
}
public IList<ErpData> GetErpDataByOrder()
{
string qryErpData = "SELECT bla FROM blubb WHERE Auftragsnummer = @paramId";
System.Diagnostics.Debug.Print("QUERY: " + qryErpData);
using (IDbConnection db = new iDB2Connection(ConfigurationManager.ConnectionStrings["csAs400"].ConnectionString))
{
if (db.State == ConnectionState.Closed)
{
db.Open();
return db.Query<ErpData>(qryErpData, new { paramId = textBoxSpool.Text }).ToList();
}
}
return null;
}
private void button1_Click(object sender, EventArgs e)
{
dataGridView1.DataSource = GetErpDataByOrder();
}
ich möchte gerne von WindowsForms auf WPF umsteigen, habe aber gelesen, dass es im Terminalserver Einsatzbereich zu Performance einbrüchen kommen kann.
Der Einsatz von Terminalserver ist absolute Vorraussetzung an die zu entwickelnde Software hier bei uns.
Wir haben hier 2 Windows 2012 R2 Terminalserver mit jeweils max. 40 gleichzeitigen Usern per LoadBalancing verteilt.
Die Server laufen in dieser Konstellation äußerst entspannt (Office, Outlook usw.).
Die zukünftigen Anwendungen sollen ohne aufwendige Animationen und 3D-Grafiken auskommen.
Hauptsächlich geht es darum versch. Datenbanksysteme abzufragen und die Daten in sinnvollen Reports (vorwiegend DataGrids, oder Formulare) druckbar darzustellen und in PDFs zu speichern.
Da die WPF ja DirectX verwendet, wollte ich mal eure Erfahrungen abklopfen, ob das auf ThinClients, die sich per RDP auf den Terminalservern anmelden, noch ausreichend performant läuft.
Gibt es vielleicht eine Test-Anwendung in WPF, die man mal zum Performance testen installieren könnte, oder hat Server 2012 R2 Bord-Apps in WPF?
Würdet ihr in meinem Falle mit WinForms weiterentwickeln oder auch auf WPF oder sogar auf ASP .NET switchen?
Das mit dem Static habe ich aus nem Tutorial von Youtube :-). das werde ich mir noch anschauen.
Das mit den Parameter habe ich hoffentlich jetzt richtig gemacht.
Dein methodenaufbau gefällt mir auch viel besser! :-)
public static IList<Address> GetAddressByAdrnr(int id)
{
string sql = "SELECT A.*, B.NAME FROM DBTEST01.ADDRESSES AS A JOIN DBTEST01.STATES AS B ON A.STATUS_ID = B.ID WHERE A.ID = @paramId";
System.Diagnostics.Debug.Print("QUERY: " + sql);
IList<Address> addresses = new List<Address>();
using (IDbConnection db = new iDB2Connection(ConfigurationManager.ConnectionStrings["csAs400"].ConnectionString))
{
if (db.State == ConnectionState.Closed)
{
db.Open();
addresses = db.Query<Address, State, Address>(
sql,
(address, state) =>
{
address.Status = state.Name;
return address;
}, new { paramId = id }, splitOn: "NAME")
.Distinct()
.ToList();
}
}
return addresses;
}
ich versuche mich gerade mit dem ORM Dapper in einem kleinen Beispielprojekt vertraut zu machen.
Es geht um das Mapping eines SQL-JOINS zweier Tabellen. Auf der Dapper-Website habe ich die Multi-Mapping Möglichkeiten gesehen, welche ich hierfür verwenden möchte.
Ich habe in der Datenbank zwei Test-Tabellen - ADDRESSES und STATES. Tabelle ADDRESSES hat eine Fremdschlüssel-Spalte namens "Status_Id" welche auf die Spalte "Id" der Tabelle STATES referenziert.
Eine Adresse kann genau einen Status haben. Den Status können aber mehrere Adressen haben.
Hier die Modelllklassen:
public class Address
{
[Key]
public int Id { get; set; }
[StringLength(20, MinimumLength = 3)]
public string Anrede { get; set; }
[StringLength(40, MinimumLength = 3)]
public string Vname { get; set; }
[StringLength(40, MinimumLength = 3)]
public string Nname { get; set; }
[StringLength(10, MinimumLength = 10)]
public string Geburt { get; set; }
[StringLength(40, MinimumLength = 3)]
public string Strasse { get; set; }
[StringLength(5, MinimumLength = 5)]
public string Plz { get; set; }
[StringLength(40, MinimumLength = 3)]
public string Ort { get; set; }
[StringLength(20, MinimumLength = 3)]
public string Telefon { get; set; }
[StringLength(40, MinimumLength = 3)]
public string Email { get; set; }
// Foreign key
[Required]
public int Status_Id { get; set; }
// State-Modell
public State Status { get; set; }
}
public class State
{
[Key]
public int Id { get; set; }
[StringLength(20, MinimumLength = 3)]
public string Name { get; set; }
}
Mit der folgenden Methode versuche ich das Abfrageergebnis in das Datenmodell zu mappen:
public static List<Address> GetAddressByAdrnr(int id)
{
string sql = "SELECT * FROM DBTEST01.ADDRESSES AS A JOIN DBTEST01.STATES AS B ON A.STATUS_ID = B.ID WHERE A.ID = " + id;
using (IDbConnection db = new iDB2Connection(ConfigurationManager.ConnectionStrings["csAs400"].ConnectionString))
{
if (db.State == ConnectionState.Closed)
{
db.Open();
var addresses = db.Query<Address, State, Address>(
sql,
(address, state) =>
{
address.Status = state;
return address;
})
.Distinct()
.ToList();
}
System.Diagnostics.Debug.Print("QUERY: " + sql);
}
return null;
}
Die Query lasse ich mir in der Fehlerliste ausgeben und kopiere ihn in ein Query-Tool, welches mir den korrekten Datensatz liefert:
SELECT * FROM DBTEST01.ADDRESSES AS A JOIN DBTEST01.STATES AS B ON A.STATUS_ID = B.ID WHERE A.ID = 5
-->
ID ANREDE VNAME NNAME GEBURT STRASSE PLZ ORT TELEFON EMAIL STATUS_ID ID NAME
5 Frau Magda Malhingehen 1945-08-01 Am Waldrand 98 56123 Waldhausen 085476822 magdamalhingehen@hotweb.com 3 3 Abgekündigt
Das Ergebnis der Methode vom Typ List<Address> wird als DataSource an ein DataGridView gebunden, welches aber leer bleibt.
Ich vermute, dass ich mein Datenmodell nicht richtig angelegt habe.
Kann mir bitte jemand helfen und erklären, was falsch läuft?
1. und 2. mache ich, habe nur noch Probleme, dies zu implementieren. Das ist doch der Weg über ORM?
3. OK, using macht try/catch/con.Close() überflüssig - werde ich.
4. Ich gebe doch auch den Wortlaut der Exception zurück, wenn auch per Direktzugriff auf das UI.
Wie händle ich aber die Exception, wenn ich try/catch (siehe Punkt 3) weglasse?
ich habe mal ein paar Fragen zu den verschiedenen Datenbank-Zugriffsmethoden, bzw. möchte ich mir Klarheit verschaffen, weil ich das Gefühl habe immer etwas falsch zu machen.
Ich hole meine Daten immer, wie im folgenden Code aus der jeweiligen Datenquelle und speichere sie zur Weiterverarbeitung in einer DataTable (hier speziell das Beispiel IBM AS/400):
using IBM.Data.DB2.iSeries;
public static DataTable GetSQLData(string qry)
{
// MessageBox.Show(conStr, "ConnectionString:");
try
{
DataTable dt = new DataTable();
using (iDB2Connection conn = new iDB2Connection(conStr))
{
conn.Open();
iDB2Command cmd = new iDB2Command(qry, conn);
iDB2DataReader reader;
reader = cmd.ExecuteReader();
dt.Load(reader);
conn.Close();
return dt;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "AS/400: Fehler bei SELECT");
return null;
}
}
Dieses DataTable kann ich mir dann über ein DataGridView anzeigen lassen oder die einzelnen DataRows auswerten.
Bisher konnte/kann ich damit gut arbeiten.
Schreibzugriffe auf die DB gingen auf ähnliche Weise bisher problemlos:
public static bool UpdateSQLData(string qry)
{
try
{
using (iDB2Connection conn = new iDB2Connection(conStr))
{
conn.Open();
iDB2Command cmd = new iDB2Command(qry, conn);
cmd.ExecuteNonQuery();
cmd.Dispose();
return true;
}
}
catch (Exception exp)
{
MessageBox.Show(exp.Message, "AS/400: Fehler bei UPDATE");
return false;
}
}
Im EntityFramework als Gegensatz wird ja die ORM-Technik verwendet, wo die entsprechenden DB-Tabellenstrukturen in eigenen Model-Klassen abgebildet (gemappt) werden.
Jeder Datensatz ist ja dann ein Objekt dieser Klasse. Ein sogenannter Kontext für die Model-Klasse liefert mir dann eine Collection (List, Dictionary...) aus den Objekten.
Mit diesem Dictionary wird dann per LINQ weitergearbeitet.
Für MS-Sql und MySql gibt es da ja freie Zugriffsmöglichkeiten aber für IBM AS/400 finde ich keinen freien AS400 .NET data provider und wir haben auch keinen lizenziert.
Ich bin also gezwungen über ODBC zu gehen. Dafür gibt es aber keine Unterstützung für das EntityFramework, wo es mir die Model-Klassen aus der DB erstellt.
Jetzt könnte ich mir die Model-Klassen ja per Hand tippen und die Kontexte dafür erstellen, was aber sehr aufwendig ist. Die Tabellen auf der AS/400 haben meist mehr als 50 Spalten.
Jetzt meine Fragen:
1. Sind meine oben genannten Zugriffsmethoden OK, zeitgemäß, sicher usw.? Wenn nicht - Was muss verbessert werden?
2. Macht es Sinn die riesigen Model-Klassen per Hand zu erstellen und sie per Kontext und LINQ zu verwenden?
3. Was ist der Vorteil von der Verwendung von EF und LINQ, wenn ich bisher mit meinen Zugriffsmethoden klar gekommen bin (Performance/Trennung Datenmodell von Logik)?
ich muss ein Programm schreiben, in dem Informationen auf Endlosetiketten gedruckt werden sollen.
Das Problem ist nur, dass ich gleichzeitig 2 Etikettendrucker mit 2 verschiedenen Etikettenformaten verwenden muss.
Kann ich also programmseitig sagen, welche Infos auf welchem Drucker gedruckt werden sollen.
Bisher habe ich immer den Windows-Standarddrucker verwendet und die Infos auf diesen Drucker geschickt.
Bei 2 Formaten funktioniert das jedoch nicht. Das Programm muss beide Drucker kennen.
Ist das prinzipiell möglich und wenn ja, wie Wie realisiert man sowas?
SQL:
----
-MySql, DB2, arbeite mich grade in MSSQL ein
Objektorientiertes Programmieren ist mir also nicht fremd.
Es geht darum, ein geeignetes Buch für den Umstieg in C# zu finden.
In C++ hat man ja immer .cpp und .h Dateien für jede Klasse erstellt. In Delphi erstellt man Units.
Das Buch sollte schwerpunktmässig darauf eingehen, gut strukturiert in C# zu programmieren.
Was gehört in welche .cs Datei usw.
Die Grundlagen (was ist ein Datentyp, Operator, Schleifen, Selektionen usw.) sollten nur oberflächlich behandelt werden da mir ja vieles aus C++ bekannt vorkommen sollte.
Was mache ich wenn ich mit MS VS 2010 C# ein Programm für Systeme ab Win2000 kompilieren will?
gfoidl schrieb ja mit Multi Targeting würde ja sowas gehen.
Geht aber nur bis .NET FW 2.0 runter --> 1.1 bleibt außen vor, oder?
Macht aber nix, auf unsere WinNT4 Mühlen soll eh nix Neues, die sollen einfach laufen solange sie noch wollen...
FAZIT:
Also ist C# für mich die "Eierlegende Wollmilchsau".
ich bin neu hier im Forum und muss mir erstmal Klarheiten über .NET und C# verschaffen.
Momentan verwende ich 2 Programmiersprachen und entwickle ausschließlich für Windows Plattformen.
Die Problematik Linux oder Mac soll für meine Anforderungen erstmal außen vor gelassen werden.
Bisher programmiere ich GUI unter Windows immer mit Turbo Delphi und finde das auch ganz OK.
Für einfache Spieleprogrammierung verwende ich C++ und die SFML-Lib.
Konsolenprogramme kann ich mit beiden Sprachen basteln.
C++ gefällt mir vom Syntax und der Struktur sehr gut, aber GUI ist doch schon relativ kompliziert.
Delphi gefällt mir in Sachen einfache GUI- Entwicklung, aber der Syntax ist schon relativ unterschiedlich zu C++.
Da ich aber nicht immer zwischen 2 Sprachen hin und herwechseln will und lieber eine Sprache richtig und für alle Zwecke verwenden möchte, kommt mir C# recht gelegen.
Für meine Zwecke scheint mir C# die eierlegende Wollmilchsau zu sein.
Das erstellen von Windows- GUI und Konsolen- Anwendungen scheint mir, nach einigen Tutorials, enorm einfach und vielseitig zu sein.
Grafik und Spiele kann man zukünftig mit XNA oder anderen Frameworks offensichtlich auch ganz gut realisieren.
Außerdem scheint mir C# und .NET äußerst zukunftssicher zu sein, wenn man Jobbörsen Glauben schenken kann.
Nun ist es aber so, dass wir in unserem Unternehmen noch einige unterschiedliche Windows Systeme am Laufen haben.
Es gibt WindNT4, Win2000, Win2003Server, WinXP und Win7 Systeme in unserem Netz.
Alle Systeme unterstützen jedoch .NET nur bis zu einem gewissen Release. Bei WinXP und Win7 mache ich mir da keine Gedanken, bei WinNT4 bis Server2003 jedoch schon.
Meine Fragen wären:
Kann man die unter .NET und Visual C# 2010 entwickelten Anwendung für die jeweiligen Systeme, also für verschiedene .NET Frameworks kompilieren?
Kann man mit C# und .NET alle möglichen Datenbank Systeme anbinden? Wichtig wären für mich MySQL, MSSQL, ODBC (speziell iSeries/DB2 über ClientAccess).