Vi håller på och utvecklar en WCF applikation med en flerlagers lösning. Där alla serverdelar datalager, business, facade osv. ligger för sig och sedan ska vi via WCF kommunicera från våran WebClient till serverdelarna. Om det är WS-AtomicTransaction du vill använda så måste du köra wsHttpBinding (det är där alla WS-* grejjer finns). Nu har jag trixat med detta i ca 1vecka utan framgång. MSDTC borde inte bli inblandad då ni som ni säger har "buntat ihop" anropen så att varje anrop till WCF == lokal transaktion. Nej det har jag inte gjort, testade detta nu men då blir det ingen transaktion. Jag har ett test som jag kör nu där jag sparar ett objekt och kastar sedan ett Exception och efter det så har jag ytterligare ett spara anrop som i praktiken aldrig kommer att köras. Men efter att ha tagit bort TransactionFlow-markeringen av kontrakten så sparas det första objekete i alla fall. Du skpar transaktionen själv genom att köra: Provade men får fortfarande samma fel. hmm, TransactionScopeRequired = true borde innebära samma sak som using(var tx = new TransactionScope()) Ja den fungerar och går in i det första anropet som ska spara det första objektet men när den går in i den metoden så får jag felete med "Denna transaktionshanterare misslyckades med att ansluta till en annan TIP-transaktionshanterare. (Exception from HRESULT: 0x8004D01F)". Låter som att VM-data grejjern inte funkar med: En grej till som jag missade attnämna: Jo då det förstod jag :) Har förresten kollat med WM-Data och det ska fungera med TransactionScope och det visste jag ju iof redan i och med att det fungerar i kundens miljö. Transaktioner med WCF och basicHttpBinding
Det jag inte får kläm på är transaktionshanteringen. Jag har fått höra att med basicHttpBinding som vi använder kan man använda sk. interna transaktioner, men har inte fått kläm på vad det är heller.
Det jag gör är att i interfacen deklarera att transactioner är tillåtet:
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
void MyMethod(SaveContract saveContract1, SaveContract saveContract2);
Implementeringen av interfacet:
[OperationBehavior(TransactionScopeRequired = true)]
public void MyMethod(SaveContract saveContract1, SaveContract saveContract2)
{
this.myFacade.Save(saveContract1);
throw new Exception("Stop transaction");
this.myFacade.Save(saveContract2);
}
Sedan har jag testat lite olika sätt från WebClient, både att inte göra något speciellt utan bara anropa servicen och MyMethod. Samt följande var det senaste jag testade:
using (TransactionScope trans = new TransactionScope(TransactionScopeOption.Required))
{
MyClient myClient = new MyClient();
myClient.MyMethod(myFirstSaveContract, mySecondSaveContract);
trans.Complete();
}
Men jag får bara detta felmeddelande: Partnertransaktionshanteraren har inaktiverat sitt stöd för fjärr- och nätverkstransaktioner. (Exception from HRESULT: 0x8004D025) Har googlat på felet och fått förslag på säkerhetsinställningar för MSDTC men utan resultat.
Jag är inte helt säker men det kanske är så att vi behöver byta ut våran basicHttpBinding mot tex wsHttpBinding. Anledningen till att jag fösöker hitta en lösning med basicHttpBinding är att applikationen är ganska stor och det kommer bli ett omfattande arbeta med att byta ut alla bindings.
Någon som har haft samma problem och har en lösning eller föslag på saker jag kan prova?
/Tack!
Sv: Transaktioner med WCF och basicHttpBinding
Är ni riktigt säker på att ni behöver transaktioner som omfattar flera WCF anrop? Jag brukar föreslå att varje anrop till tjänster hanterars som en logisk enhet("Unit of work"). Något i stil med:
public void RegisterNewCustomer(RegisterNewCustomerRequest request)
{
//starta en intern transaktion för detta service-anrop
using (TransactionScope trans = new TransactionScope(TransactionScopeOption.Required))
{
//skapa rader i customer tabellen
//skapa rader i account tabell
//osv
}
}
Mao gör man anropen till "service-lagret" lite grövre. Så att man i detta fall kan man nyttja affärslogiken för att skapa nya kunder från ex. Web-UI, Fet-klient, batchar osv. Man slipper även distribuerade transaktioner vilket är bra för prestanda m.m.Sv:Transaktioner med WCF och basicHttpBinding
Vi har precis som Andreas beskriver här över, vi "buntar" ihop anrop till underliggande lager i en metod i servicel-lagret.
Jag har testat olika inställningar för MSDTC och har kommit så långt att jag numera får följande meddelande när jag testar transaktionerna via våran applikation: "Denna transaktionshanterare misslyckades med att ansluta till en annan TIP-transaktionshanterare. (Exception from HRESULT: 0x8004D01F)"
Googlade på detta men det tips jag hittar är att jag ska slå på "Enable TIP-transactions" i MSDTC vilket jag har gjort både på applikations-servern och SQL Servern. Jag har öppnat portar hit och dit (134,135 mfl.) men inget verkar hjälpa. Det som är mest störande är att allt fungerar i kundens miljö och jag har pratat med deras tekniker så att jag använder samma inställningar osv. men inget fungerar.
Någon som har någon idé på vad jag gör för fel? Eller inställningar som jag inte har testat?
Jag kör Win XP Pro och SQL Servern är Win Server 2003.Sv: Transaktioner med WCF och basicHttpBinding
Har du tagit bort
[TransactionFlow(TransactionFlowOption.Allowed)] från ditt service kontrakt? ( för det behövs ju inte längre)Sv:Transaktioner med WCF och basicHttpBinding
Anledningen ligger nog i att vi har ett genererat datalager som har genererats av WM-Datas produkt WM-Bof som i sina spara metoder har något som heter ApplyChanges(); som fungerar lite som en transaktionens motsvarighet till Commit(); Men som jag har fått förklarat för mig så ska det fungera att markera upp kontrakten med TransactionFlow osv. för att flera anrop som utför en "Commit" ska läggas under en och samma transaktion.Sv: Transaktioner med WCF och basicHttpBinding
using (TransactionScope trans = new TransactionScope(TransactionScopeOption.Required))
{
//anropa wm-data grejjerna
}
om dessa inte har stöd för TransactionScope så får du göra nått i sitl med:
using (var trans = new VMDataTransktionEllerVadDomNuKallarDet(TransactionScopeOption.Required))
{
//anropa wm-data grejjerna
}
[OperationBehavior(TransactionScopeRequired = true)] skall du inte ha med!Sv:Transaktioner med WCF och basicHttpBinding
Det som jag tycker är mest underligt är att det fungerar fin fint i kunden miljö att använda [OperationBehavior(TransactionScopeRequired = true)]. Och det är ju bra att det fungerar där men när vi ska debugga i våran miljö så får vi det inte att fungera.Sv: Transaktioner med WCF och basicHttpBinding
Funkar debuggingen när du kör "using" varianten?
/AndreasSv:Transaktioner med WCF och basicHttpBinding
Felete verkar uppstå när själva sparningen ska ske, så jag ska försöka ta kontakt med WM-Data och höra med dom.
Tack för all hjälp, har du flera idéer så är dom välkommna!Sv: Transaktioner med WCF och basicHttpBinding
using (TransactionScope trans = new TransactionScope(TransactionScopeOption.Required))
{
//anropa wm-data grejjerna
}
utan kräver nån egen variant av "transaktionshantering", kolla hur man startar en transaktion manuellt med vm-datas grejjer!
PS med nhibernate blir det nått i stil med:
using (var session = SessionManager.Instance.GetSession())
using (var tx = session.BeginTransaction())
{
//Do work
tx.Commit();
}
Sv:Transaktioner med WCF och basicHttpBinding
Då måste givetvis köra:
trans.Complete(); För att committa när du kör med TransactionScope!Sv: Transaktioner med WCF och basicHttpBinding