2012-09-13 12 views
8

Tôi đã viết một lớp để hỗ trợ thêm & xóa đích đến mục tiêu xuất bản bằng dịch vụ cốt lõi. Các điểm đến thường được hiển thị dưới dạng một chuỗi (có nội dung XML) thông qua Dịch vụ cốt lõi, vì vậy tôi đã viết các trình bao bọc riêng của mình xung quanh đó, v.v.Làm cách nào để triển khai hỗ trợ Giao dịch WCF trên lớp tùy chỉnh bằng cách sử dụng CoreService?

Hiện tại tôi cần cập nhật 2 mục tiêu xuất bản và nghĩ rằng nó sẽ là mát mẻ để sử dụng phạm vi giao dịch để đảm bảo rằng cả hai mục tiêu đều được cập nhật cùng một lúc.

Tuy nhiên, tôi đang đấu tranh với việc thực hiện điều này.

Mã làm việc (sử dụng tiêu chuẩn CoreService WCF client):

TransactionOptions txOptions = new TransactionOptions 
        { IsolationLevel = IsolationLevel.ReadCommitted }; 
using(TransactionScope scope = new TransactionScope(
          TransactionScopeOption.Required, txOptions)) 
{ 
    PublicationTargetData publicationTarget1 = (PublicationTargetData)client.Read("tcm:0-1-65537", readOptions); 
    PublicationTargetData publicationTarget2 = (PublicationTargetData)client.Read("tcm:0-2-65537", readOptions); 

    publicationTarget1.TargetLanguage = "JSP"; 
    publicationTarget2.TargetLanguage = "JSP"; 
    client.Save(publicationTarget1, readOptions); 
    client.Save(publicationTarget2, readOptions); 

    // Stop saving 
    scope.Dispose(); 
} 

Thực thi mã này thành công sẽ quay trở lại các thay đổi mà tôi đã làm (nếu tôi phá vỡ trước scope.Dispose() và kiểm tra các chỉ tiêu công bố trên Tridion nó thay đổi thành công mục tiêu và sau đó "hoàn tác" thay đổi).

Nếu bây giờ tôi cố gắng sử dụng lớp "Mục tiêu xuất bản mở rộng" của tôi cũng trong Giao dịch, tôi không thể hủy bỏ nó.

TransactionOptions options = new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted }; 
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, options)) 
{ 
    ExtendedPublicationTarget target1 = new ExtendedPublicationTarget("tcm:0-1-65537"); 
    ExtendedPublicationTarget target2 = new ExtendedPublicationTarget("tcm:0-2-65537"); 
    target1.Destinations.Add(target1.Destinations[0]); 
    target2.Destinations.Add(target2.Destinations[0]); 
    target1.Save(); 
    target2.Save(); 
    scope.Dispose(); 
} 

Vì vậy, về cơ bản, đây là câu hỏi: Tôi phải làm gì để thêm giao dịch vào phương thức .Save() của tôi?

Tôi đã cố gắng làm điều này:

[OperationContract] 
[TransactionFlow(TransactionFlowOption.Allowed)] 
public void Save() 
{ 
    _client.Save(targetData, readOptions); 
} 

Nhưng nó không tạo sự khác biệt. Có cách nào để xác định xem tôi hiện đang trong giao dịch hay không và bằng cách nào đó "sử dụng" giao dịch đó? Tôi không muốn yêu cầu một giao dịch, chỉ muốn có tùy chọn để hoạt động trong một giao dịch.

Cảm ơn và xin lỗi vì bài đăng rất dài ... muốn đảm bảo rằng tôi đã cung cấp càng nhiều thông tin càng tốt.

+0

Vì bạn có biến 'scope' trong mệnh đề' using', bạn không nên gọi 'Dispose' trên nó một cách rõ ràng. Thay vào đó, nó sẽ tự động được xử lý khi khối 'using' kết thúc. –

+0

Bạn nói "Tôi không thể nhúng nó". Điều đó nghĩa là gì? Bạn có gặp lỗi biên dịch không? Một ngoại lệ? Hay mã không cập nhật các mục tiêu của bạn? (PS: nếu WCF giao dịch được đặt tên theo những gì tôi đang sử dụng để, một TransactionScope sẽ hoặc là "piggy back" trên một giao dịch hiện có hoặc bắt đầu một cái mới. Nhưng kể từ khi tôi không có kinh nghiệm với các giao dịch WCF, tôi muốn nhiều hơn là xem ai đó xác nhận/sửa lại giả định đó). –

+0

Hey Frank, tôi đang cố gắng để làm cho nó thất bại, do đó scope.Lispose() gọi của tôi. Trong ví dụ đầu tiên nó thất bại một cách chính xác, và trên một thứ 2 nó không. Chỉ cần cố gắng tìm ra những gì tôi cần phải thêm vào lớp học của tôi để làm cho nó hoạt động ... –

Trả lời

3

Các nguồn lực tốt nhất cho điều này là: WCF Transaction Propagation

Bạn đang thiếu ít nhất một bước. Bạn cũng cần phải kích hoạt giao dịch trong các ràng buộc:

<bindings> 
    <netTcpBinding> 
     <binding name = “TransactionalTCP” transactionFlow = “true” /> 
    </netTcpBinding> 
</bindings> 

Có cách nào để xác định xem Tôi hiện đang trong một giao dịch và bằng cách nào đó "sử dụng" giao dịch đó?

Có. Để xác định xem bạn có đang trong giao dịch hay không, bạn có thể kiểm tra Transaction.Current. Nếu bạn đang trong một giao dịch, bạn sẽ sử dụng nó trừ khi bạn chọn không tham gia rõ ràng. Đó là điều tuyệt vời/kinh khủng về giao dịch môi trường xung quanh.

Hình 5 trong WCF Transaction Propagation:

class MyService : IMyContract 
{ 
    [OperationBehavior(TransactionScopeRequired = true)] 
    public void MyMethod(...) 
    { 
     Transaction transaction = Transaction.Current; 
     Debug.Assert(transaction.TransactionInformation. 
        DistributedIdentifier != Guid.Empty); 
    } 
} 

Nếu Transaction.Current.TransactionInformation.DistributedIdentifier là trống rỗng, sau đó giao dịch là địa phương và đã không "dòng chảy". Lưu ý rằng trong cấu hình TransactionFlowOptions.Allowed nếu giao dịch không chạy được, nó không hoạt động âm thầm. Vì vậy, đây thực sự là cách duy nhất để kiểm tra ... và không chảy xảy ra dễ dàng hơn bạn mong đợi.

Khi tôi sử dụng các giao dịch cho dịch vụ sản xuất, tôi thực sự tránh được TransactionFlowOptions.Allowed vì người gọi không bao giờ chắc chắn liệu giao dịch có thực sự được chuyển hay không. Nếu có lỗi cấu hình ràng buộc trong quá trình triển khai, mọi thứ sẽ chạy tốt nhưng các lần rollback sẽ thất bại ... một lỗi rất khó phát hiện. Vì vậy, tôi chuyển sang yêu cầu. Sau đó, người gọi có thể đảm bảo giao dịch mà họ đã cung cấp đã thực sự được chuyển thành công. (Nếu giao dịch không chạy trong cấu hình TransactionFlowOptions.Required, bạn sẽ nhận được ngoại lệ.)

+0

Tuyệt vời. Tôi đã tạo ra các ràng buộc NetTCP lập trình và đã không thiết lập binding.TransactionFlow = true - sau khi làm điều này tất cả các công trình như mong đợi. Cảm ơn rất nhiều –