Sub ErmitteleSpaltenWerte()
Dim sql, UserNumber, PaletteOriginal, Spaltennummer, VarNummer
UserNumber = right( "000" & cwlstart.CurrentUser.Number, 3)
Set myvars = CWLCompany.ModifiedVars
sql = "Select * FROM G02W245" & UserNumber & " (NOLOCK) WHERE c062='" & myvars.Value(26,0) & "'"
PaletteOriginal = myvars.value(26,506)
Palette = 0
Set res = cwlstart.CurrentCompany.Connection.Select(sql)
If res>=0 Then
' Benutzerdefinierte Spaltenwerte aus temporärer Grid-Tabelle laden
' Palette
Spaltennummer = 156
VarNummer = 506
myvars.value(26,VarNummer) = res.Value("c" & Cstr(Spaltennummer))
' Rabatttext 1
Spaltennummer = 153
VarNummer = 504
myvars.value(26,VarNummer) = res.Value("c" & Cstr(Spaltennummer))
' Rabatttext 2
Spaltennummer = 154
VarNummer = 505
myvars.value(26,VarNummer) = res.Value("c" & Cstr(Spaltennummer))
' Frachtkosten
Spaltennummer = 155
VarNummer = 503
myvars.value(26,VarNummer) = res.Value("c" & Cstr(Spaltennummer))
End If
res.close
Set res = Nothing
End Sub
'Ende von (Deklarationen)
Sub CWLCompany_OnInsertTable(TableNo)
If TableNo = 26 Then
Call ErmitteleSpaltenWerte
End If
End Sub
Sub CWLCompany_OnUpdateTable(TableNo)
If TableNo = 26 Then
Call ErmitteleSpaltenWerte
End If
End Sub
Datalayer XPDictionary (Metadaten)
Die DataLayer, welche vom DataLayerManager (siehe Herstellen einer Datenverbindung) erzeugt werden, enthalten ein um die benutzerdefinierten Tabellen und Spalten erweitertes XPDictionary (https://docs.devexpress.com/XPO/DevExpress.Xpo.Metadata.XPDictionary), sofern bei der Methode CreateDataLayer die Parameter loadUserdefinedTables (für neue Tabellen) und/oder loadUserdefinedColumns für neue Spalten in Standard-Tabellen gesetzt werden.
Dieses erzeugt dann automatisch eine Column je PersistentProperty - auch derjenigen, die zur Laufzeit erzeugt wurden.
Hier ein Beispiel für die Erzeugung einer XpCollection für die BestelldateiMitte (t026) welche um benutzerdefinierte Spalten erweitert wurde:
using var uow = MesoObjectLayer.GetDataUnitOfWork();
var classInfoT026 = uow.GetClassInfo(typeof(BestelldateiMitte));
var xpCollectionT026 = new XPCollection(uow, classInfoT026);
gridControl1.DataSource = xpCollecionT026;
Im DataGrid stehen alle persistenten Properties - inkl. der benutzerdefinierten - zur Verfügung:
Filterung einer XPCollection mit benutzerdefinierten Spalten
Hier ein Beispiel für die Erzeugung einer XPCollection für den BestelldateiKopf (t025) welche um benutzerdefinierte Spalten erweitert wurde:
var connectionStringSystem = MSSqlConnectionProvider.GetConnectionString(
"DEMOSRV01\\DEMO", "meso", "*********", "CWLSYS"); ;
using var uowSystem = new SystemUnitOfWork(connectionStringSystem);
// Benutzerdefinierte Spalten und Tabellen in das XPDictionary laden
using var dal = DataLayerManager.CreateDataLayer(uowSystem, "500M",loadUserdefinedColumns:true, loadUserdefinedTables:true);
// ObjectLayer für automatische Filterung auf aktuelles Wirtschaftsjahr
var mesoObjectLayer = new MesoObjectLayer(dal, "500M");
using var uow = mesoObjectLayer.GetDataUnitOfWork();
var classInfoT025 = uow.GetClassInfo(typeof(BestelldateiKopf));
var xpCollectionT025 = new XPCollection(uow, classInfoT025, CriteriaOperator.Parse("StartsWith([Kennzeichen],'TS')"));
xpCollectionT025.Load();
foreach (var beleg in xpCollectionT025.OfType<BestelldateiKopf>())
{
Debug.WriteLine($"Beleg {beleg.Mesoprim} hat Kennzeichen {beleg.GetColumnValueDirect<string>("U000")}");
}
Dadurch werden die in der angegebenen Datenbankverbindungszeichenfolge gespeicherten benutzerdefinierten Tabellen und Spalten aus der Tabelle T132 geladen und in das XPDictionary angefügt.
/// <summary>
/// Lädt benutzerdefinierte Tabellen und Spalten in das vorhandene XPDictionary
/// </summary>
/// <param name="connectionString"></param>
/// <param name="dict"></param>
public static void LoadUserdefinedTablesAndColumns(string connectionString, XPDictionary dict)
Wenn benutzerdefinierte Spalten der Mesonic Standard-Tabellen über Vererbung implementiert werden, so hat man den Vorteil, dass die Klasse inkl. benutzerdefinierter Felder im Code vollständig zur Verfügung steht, z.B. für Linq.
Damit das Xpo-Framework jedoch erkennen kann um was für ein Objekt sich ein Datensatz handelt (also um eine Instanz der Basisklasse oder eine Instanz einer abgeleiteten Klasse) ist die Spezifikation mittels ObjectType Spalte erforderlich. Diese Spalte ist wiederum eine Referenz auf die Tabelle XpObjectType (siehe XPObjectType Class | eXpress Persistent Objects | DevExpress Documentation), welche die definierten persistenten Klassen speichert.
Um das Anlegen der notwendigen Tabelle und Spalte in der Mesonic Datenbank kann die Methode CreateObjectTypesForUserDefinedTypes der Klasse DataLayerManager verwendet werden (siehe Verwendete Methoden).
Darüber hinaus müssen die Typen bei der CreateDataLayer Methode im Parameter userdefinedTypes übergeben werden.
Beispiel Ableitungen
Klassendefinitionen
/// <summary>
/// Von ArtikelPreise T023 abgeleitet
/// </summary>
[MapInheritance(MapInheritanceType.ParentTable)]
public class ArtikelPreiseMitIstos : ArtikelPreise
{
public ArtikelPreiseMitIstos(Session session) : base(session)
{
}
private double istosMaterialkosten = default;
/// <summary>
/// U000 - Istos Materialkosten (kalkulatorisch)
/// (Länge 8, SQL Datentyp System.Data.SqlTypes.SqlDouble)
/// </summary>
[Persistent("U000")]
[Display(Name = "Istos Materialkosten (kalkulatorisch)")]
public double IstosMaterialkosten { get => istosMaterialkosten; set => SetPropertyValue(nameof(IstosMaterialkosten), ref istosMaterialkosten, value); }
}
/// <summary>
/// Von BestelldateiKopf T025 abgeleitet
/// </summary>
[MapInheritance(MapInheritanceType.ParentTable)]
public class BestelldateiKopfKennzeichen : BestelldateiKopf
{
public BestelldateiKopfKennzeichen(Session session) : base(session)
{
}
private string kfzkennzeichen = default;
/// <summary>
/// U000 - KfZ Kennzeichen
/// (Länge 20, SQL Datentyp System.Data.SqlTypes.SqlNvarchar)
/// </summary>
[Persistent("U000")]
[Display(Name = "KfZ Kennzeichen")]
[Size(20)]
public string KfzKennzeichen { get => kfzkennzeichen; set => SetPropertyValue(nameof(KfzKennzeichen), ref kfzkennzeichen, value); }
private string anhaenger = default;
/// <summary>
/// U001 - Anhänger
/// (Länge 20, SQL Datentyp System.Data.SqlTypes.SqlNvarchar)
/// </summary>
[Persistent("U001")]
[Display(Name = "Anhänger")]
[Size(20)]
public string Anhaenger { get => anhaenger; set => SetPropertyValue(nameof(Anhaenger), ref anhaenger, value); }
}
/// <summary>
/// Neue benutzerdefinierte Tabelle T699 in der WinLine-Datenbank
/// </summary>
[Persistent("T699")]
[IsUserdefinedTable]
public class Testtabelle : MesoBase
{
public Testtabelle(Session session) : base(session)
{
}
private string id = default;
/// <summary>
/// U000 - Id
/// (Länge 20, SQL Datentyp System.Data.SqlTypes.SqlNvarchar)
/// </summary>
[Persistent("U000")]
[Display(Name = "Eindeutiger Key")]
[Size(10)]
[DevExpress.Xpo.Key]
public string Id { get => id; set => SetPropertyValue(nameof(Id), ref id, value); }
private string wert = default;
/// <summary>
/// U001 - Wert
/// (Länge 255, SQL Datentyp System.Data.SqlTypes.SqlNvarchar)
/// </summary>
[Persistent("U001")]
[Display(Name = "Wert")]
[Size(255)]
public string Wert { get => wert; set => SetPropertyValue(nameof(Wert), ref wert, value); }
}
Exemplarische Verwendung
var connectionStringSystem = MSSqlConnectionProvider.GetConnectionString(
"DEMOSRV01\\DEMO", "meso", "meso@demo", "CWLSYS"); ;
using var uowSystem = new SystemUnitOfWork(connectionStringSystem);
// Abgeleitete persistente Klassen
var newTypes = new Type[]
{
typeof(ArtikelPreiseMitIstos),
typeof(BestelldateiKopfKennzeichen),
typeof(Testtabelle)
};
// Anlegen der ObjectTypes
var dict = DataLayerManager.CreateObjectTypesForUserDefinedTypes(connectionStringSystem, newTypes, false);
using var dal = DataLayerManager.CreateDataLayer(uowSystem, "500M", additionalTypes: newTypes);
// ObjectLayer für automatische Filterung auf aktuelles Wirtschaftsjahr
var mesoObjectLayer = new MesoObjectLayer(dal, "500M");
using var uow = mesoObjectLayer.GetDataUnitOfWork();
foreach (var artikelPreis in new XPQuery<ArtikelPreiseMitIstos>(uow).Take(10))
Debug.Print($"{artikelPreis.Preisartikelnummer}:{artikelPreis.IstosMaterialkosten}");
foreach (var beleg in new XPQuery<BestelldateiKopfKennzeichen>(uow).Take(10))
Debug.Print($"{beleg.Mesoprim}:{beleg.KfzKennzeichen}");
// Eigene Tabelle T699
var testobject = uow.GetObjectByKey<Testtabelle>("TestId1");
if (testobject != null)
{
uow.Delete(testobject);
uow.CommitChanges();
}
testobject = new Testtabelle(uow)
{
Id = "TestId1",
Wert ="Mein Testwert"
};
uow.CommitChanges();
Verwendete Methoden
Der DataLayerManager verwendet hierbei die Methoden DropObjectTypesForUserDefinedTypes und CreateObjectTypesForUserDefinedTypes; insbesondere die Methode DropObjectTypesForUserDefinedTypes ist für Projekte relevant, da die Spalte vor einem Update oder Datenbankupsize oder Erweiterung der Tabellen um eigene Spalten entfernt werden muss.
/// <summary>
/// Löscht die Spalte ObjectType aus den Basisklassen der angegebenen benutzerdefinierten Typen.
/// Ist der Typ nicht abgeleitet, wird auch nichts durchgeführt
/// </summary>
/// <param name="connectionStringMesoSystem"></param>
/// <param name="userdefinedTypes"></param>
public static void DropObjectTypesForUserDefinedTypes(string connectionStringMesoSystem, Type[] userdefinedTypes)
/// <summary>
/// Erzeugt die XPObjectType Datensätze in der Tabelle XPObjectType (und legt diese ggf. auch an)
/// Erweitert bei abgeleiteten Klassen die Basistabellen um die Spalte ObjectType und setzt den ObjecType auf
/// die vergebene ID in der Tabelle XPObjectType
/// </summary>
/// <remarks>
/// ACHTUNG: Hierdurch wird die Mesonic Tabellenstruktur um eine Spalte erweitert, die NICHT im Repository bekannt ist
/// Das bedeutet, wenn Datenbankupsizes gemacht werden geht diese Spalte ggf. verloren und muss neu erzeugt werden
///
/// Um weitere benutzerdefinierte Spalten zu erzeugen MUSS die Spalte vorher entfernt werden.
/// Hierfür den <paramref name="dropColumn"/> auf 'true' setzen
/// </remarks>
/// <param name="connectionStringMesoSystem"></param>
/// <param name="userdefinedTypes"></param>
/// <param name="dropColumn"></param>
/// <returns>Das XPDictionary Objekt welches die benutzerdefinierten Typen enthält</returns>
public static XPDictionary CreateObjectTypesForUserDefinedTypes(string connectionStringMesoSystem, Type[] userdefinedTypes, bool dropColumn = false)
CompanyBase - Methoden
Alle Mandantenobjekte leiten von der Klasse CompanyBase ab. Diese stellt folgende Methoden zum Zugreifen auf benutzerdefinierte Spalten bereit:
GetUserdefinedColumnValue
public T GetUserdefinedColumnValue<T>(int columnNumber)
Beispiel zum Ermitteln der benutzerdefinierten Spalte U000 für einen Artikel als int:
Assert.NotNull(artikel.GetUserdefinedColumnValue<int>(0), "Product 50001 has no user definied Column 0 of int");
SetUserdefinedColumnValue
public void SetUserdefinedColumnValue<T>(int columnNumber, T value)
Beispiel zum Setzen der benutzerdefinierten Spalte U000 für einen Artikel auf den Wert “1” als int: