Fortuna Entwickler Blog

Hier wird Ihnen geholfen

Ergebnisse Workshop 14./15. November 2017

nuGet packages

Es ist nicht sinnvoll, nuGet Packages in unsere Release-Zyklen einzubinden; dies widerspricht dem eigentlichen Sinn der nuGet Packages.

In einem Package sollen Funktionen umgesetzt werden, welche Produktunabhängig sind und allgemein Verwendet werden können, z.B. Mailversand, PDF Erstellung und Ähnliches

Empfehlung Herr Schmidt: 

Rückführung Produktspezifischer Packages in die jeweiligen Solutions

Neustrukturierung der Ordnerstruktur für Solutions

Alle Solutions in einem Ordner

Alle Webanwendungen in einem eigenen Ordner in einem Unterordner (‚web‘)

Alle Bibliotheken in einem eigenen Ordner in einigen wenigen Unterordnern (‚logic‘, ‚data‘)

Damit dann Kombination aus nuGet und Bibliotheken

Builds für Projekte automatisieren

Builds für nuGet Packages erstellen Symbole für Debugging, welche vorgehalten werden


Branches, Merges, etc.

Der aktuelle Stand kann so weiter geführt werden.

Das Verschieben von Branches kann möglicherweise in Zukunft wieder verfügbar sein. Derzeit gibt es keine andere Möglichkeit, als es so zu tun, wie wir es derzeit machen.

Herr Schmitt hat uns Alternativen zur derzeitigen Vorgehensweise aufgezeigt. Diese wären gggf. Zu diskutieren.


Event- und Fehlerlogging

Das Logging, so wie wir es derzeit betreiben ist weder performant noch sonst zu empfehlen.

Empfehlung Herr Schmidt: 

Einsatz von NLog

Umstellung aller Anwendungen auf einen Asynchronen Logger

Logging gegen einen WebService (in Azure)

Archivierung von Logs in Azure Storage

Ggf. Automatisiertes Herunterladen aus Azure Storage


Benutzer, Security

Eine eigene Benutzerverwaltung ist aufwendig, fehleranfällig und nur schwer abzusichern.

Empfehlung Herr Schmidt:

Microsoft Azure Active Directory

Vergleichsweise einfache Integration in bestehende Webanwendungen

Keine Verwendung mit VENTA möglich

Derzeit nur für Versicherungskunden

Integration in Azure Service Management, um APIs abzusichern (myPension z.B.)


Swagger

Der Einsatz von Swagger, so wie es derzeit bei uns verwendet wird, entspricht vorgesehenen Verwendung. Keine ToDos.


Oracle / Entities

Oracle ODP.NET ist nicht empfehlenswert, weil vergleichsweise langsam und schlechte Tool-Unterstützung.

DevArt for Oracle ist das Tool der Wahl für den Zugriff auf Oracle Datenbanken via Entities. Der fehlende Service seitens DevArt muss selbst geleistet werden: Neue Versionen als nuGet zur Verfügung stellen, eigene Versionshistorie vorhalten.


Sonstiges

Herr Schmitt empfiehlt die Anbindung unseres AD an Azure AD.

C# 7.0/8.0 bringt wenig sinnvolles Neues, was wir nicht schon kennen

ASP.NET Core bringt für uns keine Vorteile, solange wir nicht mit Docker und/oder anderen Betriebssystemen arbeiten.

Angular.js (oder React.js oder Vue) sind Frameworks, die interessant sein können und gesondert betrachtet werden müssten.

TypeScript als Ersatz für JavaScript ist empfehlenswert.

JavaScript in Webseiten selbst sollte überhaupt nicht benutzt werden, sondern immer in eigene Dateien (dann auch als TypeScript) ausgelagert werden.


Fotos


Themen_Workshop.pptx (578,3KB)

Transfer von DBWEBTESTDMZ1 nach DBWEBTEST3

  1. Erstellen eines Exports auf DBWEBTESTDMZ1
    Über die Eingabeaufforderung auf dem Datenbankserver wird mittels des Kommandos EXPDP (https://oracle-base.com/articles/10g/oracle-data-pump-10g) ein kompletter Datenbankdump erstellt. Hierfür verwendet werden die Batchdatei 'fullexport_dbwebtestdmz1.bat' und dir darin verwiesene 'fullexport_dbwebtestdmz1.dat' (siehe Attachments). bei Anderen Datenbankservern müssen die Namen / Logindaten entsprechend angepasst werden.

  2. Erstellen einer neuen Datenbank auf DBWEBTEST3
    Über die Anwendung 'Datenbank-Konfigurationassistent' wird eine neue Datenbank erstellt:

    Zu beachten ist hier insbesondere der verwendete Zeichensatz. Das abgefragte "dbora"-Kennwort ist das Kennwort des entsprechenden Windows-Benutzers. Wichtig ist auch, den Haken bei 'Als Containerdatenbank erstellen' zu entfernen, da dies Implikationen auf die Lizenzen hätte. Mit Klick auf 'Weiter' wird dann die Datenbank erstellt und steht nach kurzer Zeit zur Verfügung.

  3. Konfigurieren und starten des Listeners
    Der Listener auf dem Server muss einmalig erstellt werden. Dies kann entweder über das Tool 'netca' erfolgen, welches über die Kommandozeite aufgerufen wird, oder man erstellt einfach unter {ORACLE_HOME}/NETWORK/ADMIN (das Verzeichnis, in dem auch tnsnames.ora und sqlnet.ora liegen) eine Textdatei listener.ora (Beispieldatei siehe Attachments). Der Listener muss dann noch einmalig über die Eingabeaufforderung mittels 'lsnrctl start' gestartet werden (https://docs.oracle.com/cd/B16351_01/doc/server.102/b14196/network004.htm).

  4. Notwendige Datenbankobjekte erstellen
    Spezifisch für diesen aktuelle Transfer wurden einige Objekte vorab angelegt.
    Dies ist zum einen der Tablespace. Dieser wurde initial auf 20GB gesetzt und wie in der Entwicklungs- und Produktionsumgebung WEBDATA genannt (anders als auf DBWEBTESTDMZ1; hier hiess er DATA01).
    Desweiteren wird der User GUTSUPER mit DBA-Rechten angelegt. Es werden diverse Rollen erstellt und diesen Rechte erteilt und zuletzt noch Database Links erstellt. Bei Erstellung der Links ist darauf zu achten, daß auch tatsächlich eine Verbindung zum Zielserver hergestellt werden kann. Dies kann man in der Eingabeaufforderung mit 'TNSPING [Servername]' testen. Der Ping muss erfolgreich sein, ansonsten fehlen hier ggf. entsprechende Konfigurationen in Firewall/Proxy.
    Das Vollständige Script 'Neuinstallation Datenbank.txt' ist in den Attachments enthalten.

  5. Import der Daten und Strukturen aus DMWEBTESTDMZ1
    Zuletzt werden dann Strukturen und Daten aus dem Datenbankdump (siehe 1.) mittest IMPDP (https://oracle-base.com/articles/10g/oracle-data-pump-10g) übernommen. Dies geschieht über eine Batchdatei 'Fullimport_DBWEBTEST3.bat' und die darin verwiesene Konfigurationsdatei 'Fullimport_DBWEBTEST3.dat'.
    Im vorliegenden Fall wurden nur die Schemas WEBDATA, WEBFRW, WEBSERVICES übernommen. Dies ist ggf. in der Konfigurationsdatei anzupassen. Die Transformation des Tablespaces (DATA01 zu WEBDATA, siehe 4.) wird in der Konfigurationsdatei berücksichtigt (Dateien siehe Attachments)


Attachments

fullexport_dbwebtestdmz1.bat (82B)


listener.ora (580B)

Neuinstallation Datenbank.txt (1,8KB)

Fullimport_DBWEBTEST3.bat (79B)

SQL Statements bei Entities monitoren

Da wir meistens mit Entities arbeiten in unseren .NET-Anwendungen, kriegen wir hierbei gar nicht so mit, welche Statements eigentlich an die DB abgeschickt werden. Hierfür gibt es von DevArt ein sehr gutes Tool: DBMonitor

Mit dem DBMonitor hat man die Möglichkeit den gesamten Datenbank-Traffic, der innerhalb einer Anwendung läuft, zu beobachten.

Der DBMonitor kann ohne zusätzliche Kosten hier heruntergeladen werden:

https://www.devart.com/dbmonitor/download.html

Wenn das Tool heruntergeladen wurde, einfach lokal auf dem Entwicklungsrechner installieren und starten.

Nun muss noch der Anwendung, die man monitoren möchte, gesagt werden, dass die Daten an den DBMonitor geschickt werden. Dazu ist es erforderlich, dass man zwei Assemblies der Anwendung hinzufügt:

  • Devart.Data
  • Devart.Data.Oracle
Anschließend muss eine Instanz von OracleMonitor innerhalb des Codes der Anwendung angelegt und aktiviert werden. Dies macht am besten relativ früh in der Anwendung, aber auf jeden Fall bevor die Statements an die DB abgeschickt werden. Mehr muss man nicht im Code verändern:

var monti = new OracleMonitor() { IsActive = true };

Wenn man nun seine Anwendung ausführt, wird sämtliche Datenbank-Traffic im DBMonitor angezeigt:



Ebenso kann man dadurch sehen, welche Statements zu Fehlern geführt haben:



Durch Anklicken dieser Zeile, wird im unteren Bereich des DBMonitor eine Detailansicht generiert, die Auskunft über das Statement, die Parameter und auch den Fehler selber liefert:







TabletWorld Showroom aufsetzen

Was ist bereits vorhanden:

TWWEBSHOW

  • Microsoft Windows Server 2008R2
  • Apache Tomcat (konfiguriert für VENTA)
  • Microsoft Internet Information Server (konfiguriert für Fortuna)
  • ...

TWDBSHOW

  • Oracle DB
  • User GUTINGIA, WEBDATA, WEBFRW, WEBSERVICES, VENTA-User
  • ...


Was ist zu tun:

TWWEBSHOW

  • Kopieren der aktuellen Version von VENTA
  • Kopieren der aktuellen Version der iPad App
  • Publilshen der aktuellen Version der Fortuna-Anwendungen
  • ...

TWDBSHOW

  • Anlegen der Tabellen / Views / Functions etc. für VENTA
  • Anlegen der Tabellen / Views / Functions etc. für Fortuna
  • Anlegen der Tabellen / Views / Functions etc. für VWS / GPS
  • Übernehmen von Basisdaten
  • Automatisiertes Befüllen von Anfangsdaten (per Script)
  • ...


Die Excel-Tabelle enthält eine Übersicht über die Tabellen in WEBDATA, WEBFRW, WEBSERVICES und GUTINGIA. Man sollte diese Übersicht als Basis dafür nehmen, welche Tabellen ob und wie gefüllt werden müssen. Auf Basis dieser Übersicht lässt sich dann ein Script entwickeln.

Tabellen Januar 2016.xlsx (53KB)

TabletWorld Showroom

Server für Tabletworld Showroom:

TWWEBSHOW

  • Windows Server 2008R2
  • 8GB RAM,  2 CPU
  • 10.98.98.163 (intern)
  • 81.20.117.20 (extern)
  • http://showroom.honorarkonzept.de
  • Apache Tomcat (Port 80)
  • Microsoft IIS (Port 88)

TWDBSHOW

  • Windows Server 2008R2
  • 8GB RAM, 2 CPU
  • 10.98.98.164 (intern)
  • Oracle DB
  • Oracle AppServer
  • dbshow (VWS/GPS-DB)
  • iasshow (Forms)

Voraussichtliche Aufwände: 1x/ Jahr je 3 Tage


Grundeinrichtung ohne Daten:

VENTA -> Christian? Ist das möglich?

VWS / GPS -> Torsten / Klaus / Helge (IAS)

Fortuna -> Christoph

Venta / iPad App (Tablet) -> Christoph

Infrastruktur / BS /WS -> Erico


Aktualisierung von DevArt Oracle DLL

Nach einer Übergabe in die Produktonsumgebung wird die aktuelle Version von DevArt geladen und unter \\VCENTER2\Entwickler-Tools\Datenbank\devart abgelegt.
Alle Entwickler aktualisieren daraufhin ihre lokale Installation von DevArt
Zudem wird der Entwicklungsserver //WEBENTW3 und der Buildserver //BUILDSERVER aktualisiert.
Diese Version bleibt dann unverändert und wird nciht im laufenden Entwicklungsprozess erneut aktualisiert.

Zur Übergabe auf die Testumgebung wird DevArt auf dem Testserver //WEBTESTDMZ3 aktualisiert und die Übergabe durchgeführt.

Nach der Übergabe in die Produktionsumgebung wird wieder wie oben verfahren.

Ausnahme von diesem Vorgehen: Es tritt in der Entwicklung ein Fehler auf, welcher auf die aktuell verwendete DevArt-Version schliessen lässt und durch eine neuere DevArt-Version beseitigen lässt. In diesem Falle wird die neue Version von DevArt geladen und unter \\VCENTER2\Entwickler-Tools\Datenbank\devart abgelegt, lokal, auf der Entwicklungsumgebung und dem Buildserver installiert.


Auswertungen Tschechien

Jeden Monat benötigt Finanzen eine Reihe von Auswertungen. Diese gehen als Excel-Tabellen an Almut bzw. deren Vertretung.

BCAS schick üblicherweise zwischen dem 21. und 23. jeden Monats die Daten an den Service. Die Daten sind dann auf WEBDATA abgelegt. Alle relevanten Tabellen beginnen mit 'BCAS'.

Bevor die Auswertungen erstellt werden, muss der Status bei jedem Vertrag geprüft und ggf. aktualisiert werden. Dies passiert durch den Aufruf einer Stored Procedure:

EXEC BCAS_IO.BCAS_STATECHANGE();

Anschliessend können die Reports abgerufen werden. Das Ergebnis wird jeweils in einer Excel-Datei gespeichert; der Dateiname steht im Kommentar über dem jeweiligen Statement (MM_YYYY austauschen gegen Monat / Jahr)

-- Exportdatei: BCAS_POLICYOVERVIEW_MM_YYYY
SELECT * FROM BCAS_POLICYOVERVIEW ORDER BY UEBERMITTELT_AM, POLICYNUMBER;

-- Exportdatei: BCAS_PAYMENTOVERVIEW_MM_YYYY
SELECT * FROM BCAS_PAYMENTOVERVIEW ORDER BY UEBERMITTELT_AM, POLICYNUMBER;

-- Exportdatei: BCAS_PAYMENTOVERVIEW_BY_MONTH_MM_YYYY
SELECT * FROM BCAS_PAYMENTOVERVIEW_BY_MONTH;

-- Exportdatei: BCAS_POLICYOVERVIEW_MONTHLY_MM_YYYY
SELECT * FROM BCAS_POLICYOVERVIEW_MONTHLY bpm;

-- Exportdatei: Monatsübersicht_YYYY_MM

--Monatsübersicht: + Commission SK
SELECT
			TO_CHAR(bp.UEBERMITTELT_AM, 'YYYY-MM') AS Monat,
			SUM(bp."value") AS  "Gebuchte Beiträge",
      0 AS "Rücklaufleistung",
      0 AS "Todesfallleistung",
      SUM(ROUND(bp.IC_BCAS / 12, 0)) AS "Provision BCAS",
      SUM(ROUND(bp.IC_SK / 12, 0)) AS "Provision SK",
      SUM(ROUND((bp.IC_SK) / 12, 0)) +ROUND(SUM(bp."Diff"), 0) AS "Provision SK2",
--	ROUND(SUM(bp."Diff"), 0) AS "Diff",
			ROUND(SUM(bp.RE / 12), 0) AS "RV-Beiträge",
      0 AS "RV-Leistungen",
      ROUND(SUM(bp.RE) / 12 * 2.5 / 100, 0) AS "RV-Provisionen",
			ROUND(SUM(ROUND(bp.C, 0) / 12), 0) AS "Costs of Insurance"
	FROM BCAS_PAYMENTOVERVIEW bp
  GROUP BY TO_CHAR(bp.UEBERMITTELT_AM, 'YYYY-MM')--, BP1.STATE
  ORDER BY TO_CHAR(bp.UEBERMITTELT_AM, 'YYYY-MM')--, BP1.STATE
	;


Als weiteren Report gibt es eine Statusübersicht. Diese wird monatlich fortgeschrieben. Man führt also das nachfolgende SQL-Statement aus, kopiert den Report des Vormonats und fügt die Daten des neuen Monats hinzu:

-- Juli 2014
WITH SEL_WERTE AS (SELECT TO_DATE('31.07.2014', 'DD.MM.YYYY') AS SEL_DATE FROM DUAL)
SELECT  BS.ID AS STATEID, BS."name" AS STATE, COUNT(SEL.ID) AS ANZAHL, NVL(SUM(SEL2.PAYMENT), 0) AS PAYMENT, NVL(SUM(SEL.SUMASSURED), 0) AS SUMASSURED
  FROM  BCAS_STATE BS
  LEFT OUTER JOIN
  (
    SELECT BP.ID, BCAS_IO.BCAS_IP_STATE_BY_DATE(BI.ID, (SELECT SEL_DATE FROM SEL_WERTE)) AS STATEID, BI.SUMASSURED
      FROM  BCAS_TRANSFER BT
      INNER JOIN BCAS_POLICY BP ON BT.ID = BP.TRANSFERID
      INNER JOIN BCAS_INSURANCEPRODUCT BI ON BP.ID = BI.POLICYID
      WHERE BT.CREATINGDATE <= (SELECT SEL_DATE FROM SEL_WERTE)
  ) SEL ON BS.ID = SEL.STATEID
  LEFT OUTER JOIN
  (
    SELECT BP.POLICYID, SUM(BP."value") AS PAYMENT
      FROM BCAS_PAYMENT BP
      WHERE BP.BOOKINGDATE <= (SELECT SEL_DATE FROM SEL_WERTE)
      GROUP BY BP.POLICYID
  ) SEL2 ON SEL.ID = SEL2.POLICYID
GROUP BY BS.ID, BS."name"
ORDER BY BS.ID;

Wichtig ist es natürlich, den Monat bzw. das Datum in Zeile 1 anzupassen. Es ist immer das Datem des letzten Tages des Monats einzutragen.

Auswertung Tschechien.sql (12,46 kb)

Datenübernahme MV: Riester

Im TFS unter Fortuna/Tools/Fortuna.MuenchenerVerein/ExcelTrasition gibt es eine Solution Fortuna.MuenchenerVerein.ExcelTrasition. Hier gibt es Klassen zu Übernahme der Excel-Daten in eine Oracle Datenbank.

Die Excel-Dateien von MV sind im Projekt enthalten. Gibt es neue Daten, müssen diese ausgetauscht werden.

Ebenso enthalten ist ein Script zur Erzeugung der Datenbanktabellen.

Um die Daten zu Übernehmen gibt es eine ganze Reihe von Tests (zu sehen über den Testexplorer. Diese Test können/müssen einzeln oder en bloc ausgeführt werden. Die Ausführungszeit liegt bei ca. 30 Minuten (Stand September 2013)

 

Datenübername MV: OASIS/LIFE/COR_ADMIN

Im Rahmen des Projektes MV sind diverse Versicherungsdaten aus MV Systemen in myLife System zu übernehmen.

Tätigkeiten zur Übernahme von Personendaten:

OASIS, LIFE und COR_ADMIN werden benötigt. Das eigentliche 'Zusammentragen' der Daten geschieht auf Mig_MVR

Mig_MVR benötigt Zugriff auf COR_ADMIN, LIFE und OASIS:

-- Ausführen auf COR_ADMIN
select  'grant select on COR_ADMIN.'||object_name||' to Mig_MVR with Grant Option;'
from    all_objects 
where   object_type in ('VIEW','TABLE')
and     object_name not like 'BIN$%==$0'
and owner = 'COR_ADMIN'

UNION

select  'grant execute on COR_ADMIN.'||object_name||' to Mig_MVR with Grant Option;'
from    all_objects 
where   owner = 'COR_ADMIN'
and     object_name not like 'BIN$%==$0'
and object_type in ('FUNCTION', 'PROCEDURE', 'PACKAGE');


-- Ausführen auf OASIS
select  'grant select on OASIS.'||object_name||' to Mig_MVR with Grant Option;'
from    all_objects 
where   object_type in ('VIEW','TABLE')
and     object_name not like 'BIN$%==$0'
and owner = 'OASIS'

UNION

select  'grant execute on OASIS.'||object_name||' to Mig_MVR with Grant Option;'
from    all_objects 
where   owner = 'OASIS'
and     object_name not like 'BIN$%==$0'
and object_type in ('FUNCTION', 'PROCEDURE', 'PACKAGE');


-- Ausführen auf LIFE
select  'grant select on LIFE.'||object_name||' to Mig_MVR with Grant Option;'
from    all_objects 
where   object_type in ('VIEW','TABLE')
and     object_name not like 'BIN$%==$0'
and owner = 'LIFE'

UNION

select  'grant execute on LIFE.'||object_name||' to Mig_MVR with Grant Option;'
from    all_objects 
where   owner = 'LIFE'
and     object_name not like 'BIN$%==$0'
and object_type in ('FUNCTION', 'PROCEDURE', 'PACKAGE');

Die Ausgaben der Statements müssen wiederum jeweils auf den beschriebenen Servern ausgeführt werden.

Zusätzlich braucht Mig_MVR noch weitere Berechtigungen:

grant select on BANK to Mig_MVR with Grant Option;

Auf Mig_MVR werden anschliessend diverse Views angelegt (MYLIFE_Mig_MVR_VIEWS.sql (14,39 kb)).

 

Oracle als Linked Server in SQL Server eintragen

Um aus einem SQL Server heraus auf eine Oracle Datenbank zuzugreifen benötigt man auf dem SQL Server Rechner ein paar Einstellungen / Programme:

1: \\VCENTER2\Entwickler-Tools\Datenbank\Oracle\ODAC1120320_x64.zip entpacken und setup.exe ausführen

(bei 32bit Systemen verwendet man ODAC1120320Xcopy_32bit.zip im gleichen Verzeichnis)

2: Durch die Installation einfach durchklicken und Standard installieren

3: Im SQL Server Manager gibt es nun unter Serverobjekte -> Verbindungsserver -> Anbieter einen Eintrag OraOLEDB.Oracle. Bei diesem Eintrag in den Eigenschaften muss die Option In Process zulassen gesetzt werden.

4: tsnames.ora und sqlnet.ora anpassen. Beispiele:

sqlnet.ora:

# SQLNET.ORA Network Configuration File: C:\ora92\network\admin\sqlnet.ora
# Generated by Oracle configuration tools.
NAMES.DEFAULT_DOMAIN = gutingia.local
SQLNET.AUTHENTICATION_SERVICES= (NONE)
NAMES.DIRECTORY_PATH= (TNSNAMES, HOSTNAME)

tsnames.ora:

DBWEB1.gutingia.local =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = DBWEB1)(PORT = 1521)))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SID = DBWEB1)))

DBWEBTESTDMZ1.gutingia.local =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = DBWEBTESTDMZ1)(PORT = 1521)))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SID = DBWEBTESTDMZ1)))

DBWEBENTW3.gutingia.local =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = DBWEBENTW3)(PORT = 1521)))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SID = DBWEBENTW3)))

DBPROD1.gutingia.local =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = DBPROD1)(PORT = 1521)))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SID = DBPROD1)))

TWDB.gutingia.local =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = TWDB)(PORT = 1521)))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SID = ventaDB)))

5: einen Linked Server erstellen und Zugriff testen. Beispiel:

EXEC master.dbo.sp_addlinkedserver @server = N'ENTWWEB01', @srvproduct=N'OraOLEDB', @provider=N'OraOLEDB.Oracle', @datasrc=N'DBWEBENTW3'
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'ENTWWEB01',@useself=N'False',@locallogin=NULL,@rmtuser=N'WEBDATA',@rmtpassword='######'

EXEC master.dbo.sp_addlinkedserver @server = N'ENTWWEB02', @srvproduct=N'OraOLEDB', @provider=N'OraOLEDB.Oracle', @datasrc=N'DBWEBENTW3'
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'ENTWWEB02',@useself=N'False',@locallogin=NULL,@rmtuser=N'WEBFRW',@rmtpassword='######'

EXEC master.dbo.sp_addlinkedserver @server = N'ENTWWEB03', @srvproduct=N'OraOLEDB', @provider=N'OraOLEDB.Oracle', @datasrc=N'DBWEBENTW3'
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname=N'ENTWWEB03',@useself=N'False',@locallogin=NULL,@rmtuser=N'WEBSERVICES',@rmtpassword='######'
GO


6: Erledigt. Jetzt ist z.B. Sowas möglich:

SELECT * 
    FROM ENTWWEB03..WEBSERVICES.ASPNET_USERS au
    INNER JOIN ENTWWEB03..WEBSERVICES.ASPNET_USER_EXTENSIONS aue ON au.USERID = aue.USERID
    INNER JOIN PRODDB01..GUTINGIA.P p ON aue.PNR = p.p_NR AND p.HIST_KZ = 2;

Also JOINs über verschiedene Users hinweg. Ohne Synonyme und Ähnliches.