2010-05-26 19 views
8

OK, tôi muốn đảm bảo rằng tôi đã đề cập đến hoàn cảnh của mình và mọi thứ tôi đã thử kỹ lưỡng. Tôi khá chắc chắn những gì tôi cần/muốn có thể được thực hiện, nhưng tôi đã không hoàn toàn tìm thấy sự kết hợp hoàn hảo cho sự thành công.Vấn đề serialization EF4 POCO WCF (không tải chậm, proxy/không proxy, tham khảo vòng tròn, v.v.)

Tôi đang sử dụng Entity Framework 4 RTM và POCO hỗ trợ. Tôi đang tìm cách truy vấn đối tượng (Config) có chứa mối quan hệ nhiều người nhiều-nhiều, với một thực thể khác (Ứng dụng). Tôi tắt tắt tải xuốngtắt tính năng tạo proxy cho ngữ cảnh và tải rõ ràng thuộc tính điều hướng (thông qua .Include() hoặc .LoadProperty()). Tuy nhiên, khi thuộc tính điều hướng được tải (tức là, Ứng dụng được tải cho một Cấu hình đã cho), các đối tượng Ứng dụng đã được tải đã chứa tham chiếu đến các Configs đã được đưa vào bộ nhớ. Điều này tạo ra tham chiếu vòng tròn .

Bây giờ tôi biết rằng DataContractSerializer WCF sử dụng có thể xử lý tài liệu tham khảo hình tròn, bằng cách thiết lập preserveObjectReferences tham số là true. Tôi đã thử điều này với một vài triển khai thuộc tính khác nhau mà tôi đã tìm thấy trực tuyến. Nó là cần thiết để ngăn chặn các "đồ thị đối tượng chứa tham chiếu vòng tròn và không thể được serialized" lỗi. Tuy nhiên, nó không ngăn cản việc tuần tự hóa toàn bộ biểu đồ, qua lại giữa Config và App.

Nếu tôi gọi nó qua WcfTestClient.exe, tôi nhận được một stackoverflow (ha!) Ngoại lệ từ khách hàng và tôi đang hosed. Tôi nhận được kết quả khác nhau từ các môi trường gọi khác nhau (thử nghiệm đơn vị C# với tham chiếu cục bộ tới dịch vụ web xuất hiện để hoạt động ok mặc dù tôi vẫn có thể khoan qua lại giữa Configs và Apps, nhưng gọi nó từ môi trường coldfusion chỉ trả về Config đầu tiên Mục tiêu chính của tôi là có một biểu diễn được tuần tự hóa của biểu đồ mà tôi tải một cách rõ ràng từ EF (ví dụ: danh sách Configs, mỗi ứng dụng của họ, nhưng không có Ứng dụng quay lại điều hướng Config.)

LƯU Ý: Tôi cũng đã thử sử dụng kỹ thuật ProxyDataContractResolver và duy trì tính năng tạo proxy được bật từ ngữ cảnh của tôi. Điều này thổi lên phàn nàn về các loại không rõ gặp phải. Tôi đọc rằng ProxyDataContractResolver không hoàn toàn làm việc trong Beta2, nhưng nên làm việc trong RTM.

Đối với một số tài liệu tham khảo, đây là khoảng cách tôi truy vấn dữ liệu trong các dịch vụ:

var repo = BootStrapper.AppCtx["AppMeta.ConfigRepository"] as IRepository<Config>; 
repo.DisableLazyLoading(); 
repo.DisableProxyCreation(); 

//var temp2 = repo.Include(cfg => cfg.Apps).Where(cfg => cfg.Environment.Equals(environment)).ToArray(); 
var temp2 = repo.FindAll(cfg => cfg.Environment.Equals(environment)).ToArray(); 
foreach (var cfg in temp2) 
{ 
    repo.LoadProperty(cfg, c => c.Apps); 
} 

return temp2; 

Tôi nghĩ rằng mấu chốt của vấn đề của tôi là khi tải lên các thuộc tính định hướng cho các đối tượng POCO từ Entity Framework 4, nó chuẩn bị sẵn các thuộc tính điều hướng cho các đối tượng đã có trong bộ nhớ. Điều này lần lượt đưa lên tuần tự hóa WCF, mặc dù mọi nỗ lực được thực hiện để xử lý đúng các tham chiếu vòng tròn.

Tôi biết đó là rất nhiều thông tin, nhưng nó thực sự đứng trong tầm tay của tôi về phía trước với EF4/POCO trong hệ thống của chúng tôi. Tôi đã tìm thấy một số bài viết và blog chạm vào những chủ đề này, nhưng đối với cuộc sống của tôi, tôi không thể giải quyết vấn đề này. Chỉ cần đặt câu hỏi và giúp tôi suy nghĩ về tình huống này.

PS: Để tận dụng triệt để, tôi đang tiêm dịch vụ WCF bằng cách sử dụng bản dựng HEAD của Spring.NET để khắc phục Spring.ServiceModel.Activation.ServiceHostFactory. Tuy nhiên tôi không nghĩ rằng đây là nguồn gốc của vấn đề.

EDIT: Lớp ProxyDataContractResolver hoạt động chính xác nếu tôi không có tham chiếu vòng tròn. (ví dụ: tôi làm cho setter của App.Configs là riêng tư, ngăn chặn serialization của tài sản.) Nó thổi lên, nó xuất hiện, khi nó chạm Configs thông qua đối tượng App - họ dường như không được công nhận là cùng loại với Configs cấp cao nhất.

EDIT2: Dường như EF hoặc WCF không nhận ra rằng các thực thể thực sự là bằng nhau. tức là: 'Config' giống như 'Config.Apps [x] .Configs [y]'. Các khóa thực thể được đặt đúng trong CSDL cho mỗi mô hình và tôi đã ghi đè hàm Equals() để so sánh các thực thể dựa trên thuộc tính 'Id' của chúng. Điều này phù hợp với các triệu chứng như không có lỗi tham chiếu vòng tròn được ném, nhưng nó thực sự là một tham chiếu vòng tròn (và thổi lên WcfTestClient.exe) VÀ ProxyDataContractResolver thổi lên khi nó chạm mức 'Config.Apps [x] .Configs [y]' của Configs. (Nó không biết cách ánh xạ một proxy Config. ProxyDataContractResolver hoạt động theo cách khác. Nó giống như nó biết cách xử lý vòng ban đầu của các thực thể, nhưng cấp thứ hai mà nó coi là các thực thể khác nhau.)

Wow, tôi có thể được dài dòng. Xin lỗi các bạn!

+0

Tôi có chính xác cùng một câu hỏi/Issue ngay bây giờ. Khuôn khổ thực thể 5.0. Các mô hình thực thể hoạt động nhưng không thể tuần tự hóa dường như để tìm ra rằng nó không nên quay trở lại một lần nữa khi sử dụng nhiều đến nhiều mối quan hệ –

+0

Đã có cùng một vấn đề, giải quyết bản thân mình. Đây là giải pháp: http://stackoverflow.com/a/17063364/1386781 –

+0

WCFTestClient không thể xử lý tham chiếu vòng tròn. Xem này [SO thread] [1] [1]: http://stackoverflow.com/questions/8686960/wcftestclient-exe-not-able-to-handle-circular-reference – MickyD

Trả lời

0

Thử đặt myContext.ContextOptions.ProxyCreationEnabled = false;

Nếu vấn đề được giải quyết (như tôi) sau đó bạn đã không làm theo các bước nêu tại: http://msdn.microsoft.com/en-us/library/ee705457.aspx

này đã giải quyết được vấn đề đối với tôi.

+0

Tôi đã thực hiện theo cả hai cách: "Tôi tắt tải chậm và tắt tạo proxy cho ngữ cảnh và tải rõ ràng thuộc tính điều hướng (hoặc thông qua .Include() hoặc .LoadProperty()) .Tuy nhiên, khi thuộc tính điều hướng được tải (nghĩa là, Ứng dụng được tải cho một Cấu hình đã cho), các đối tượng Ứng dụng đã được tải đã chứa tham chiếu đến các Configs đã được đưa vào bộ nhớ. Điều này tạo ra một tham chiếu vòng tròn. " – kdawg

1

hrmm, tôi có thể chưa hiểu đầy đủ vấn đề, nhưng mỗi lần tôi chạy tham khảo vòng tròn với WCF câu trả lời là thay đổi [DataContract] trên các lớp vi phạm thành [DataContract (IsReference = true)].

Đây là một trợ giúp rất lớn so với tất cả các drek của rối tung với các giải quyết hợp đồng cần thiết trước WCF 3.5 SP1.

Hy vọng điều này sẽ hữu ích.

2

Bạn có thể muốn xem blog post on this specific scenario của mình - hãy gửi email cho tôi nếu nó không giúp khắc phục tình trạng khó khăn hiện tại của bạn! Tôi đã bao gồm một giải pháp mẫu là tốt.

Vui lòng thả cho tôi một số phản hồi theo cách nào đó, tôi thực sự muốn nghe nhiều người hơn về vấn đề cụ thể này - đặc biệt là với các vấn đề triển khai khi khách hàng kết thúc.

+0

Hey Rob, tôi đã thử giải pháp MSDN và tôi đã có thể trả về một thực thể, nhưng không phải không có đối tượng của nó cho một bảng khác. Đọc sách -> Tác giả, tôi chỉ nhận được Sách nhưng tôi không có Tác giả. Có phải vì chúng không được sắp xếp theo thứ tự? –

+0

@LeoLuis Có thể bạn đã bật tải chậm? – RobS

1

Đối mặt với cùng một vấn đề ngày hôm nay và sử dụng Value Injecter để giải quyết vấn đề. Nó đơn giản như:

var dynamicProxyMember = _repository.FindOne<Member>(m=>m.Id = 1); 
var member = new Member().InjectFrom(dynamicProxyMember) as Member; 

Chúng tôi couldnt đủ khả năng vô hiệu hóa ProxyCreation

+1

Bạn không có ý tưởng bao nhiêu thời gian bạn đã lưu tôi ngày hôm nay. – CoachNono

+0

vui mừng vì đã giúp một nhà phát triển đồng nghiệp @CoachNono – Korayem

0

Bạn có thể sử dụng ApplyDataContractResolverAttributeProxyDataContractResolver cùng với CyclicReferencesAwareAttribute. Lúc đầu này tạo ra lỗi như thế này - như nếu không có DataContractResolver quy định tại tất cả:

Loại 'System.Data.Entity.DynamicProxies.Whatever_E6 ...... A9' bằng tên hợp đồng dữ liệu 'Whatever_E6 ...... A9: http: //schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies 'không được mong đợi. Hãy xem xét sử dụng một DataContractResolver hoặc thêm bất kỳ loại không được biết đến tĩnh danh sách các loại đã biết - ví dụ, bằng cách sử dụng thuộc tính KnownTypeAttribute hoặc bằng cách thêm chúng vào danh sách các loại đã biết được truyền cho DataContractSerializer.

Nó sẽ hoạt động với một thay đổi đơn giản.

Trong ứng dụng ApplyCyclicDataContractSerializerOperationBehavior, các hàm tạo cho DataContractSerializer cũng phải vượt qua trong DataContractResolver. Đây là tất cả các phiên bản tôi đã xem trực tuyến.

Ví dụ:

public class ApplyCyclicDataContractSerializerOperationBehavior : DataContractSerializerOperationBehavior 
{ 
    private readonly Int32 _maxItemsInObjectGraph; 
    private readonly bool _ignoreExtensionDataObject; 

    public ApplyCyclicDataContractSerializerOperationBehavior(OperationDescription operationDescription, Int32 maxItemsInObjectGraph, bool ignoreExtensionDataObject, bool preserveObjectReferences) 
     : base(operationDescription) 
    { 
     _maxItemsInObjectGraph = maxItemsInObjectGraph; 
     _ignoreExtensionDataObject = ignoreExtensionDataObject; 
    } 

    public override XmlObjectSerializer CreateSerializer(Type type, String name, String ns, IList<Type> knownTypes) 
    { 
     return new DataContractSerializer(type, name, ns, knownTypes, 
      _maxItemsInObjectGraph, 
      _ignoreExtensionDataObject, 
      true, 
      null /*dataContractSurrogate*/, 
      DataContractResolver); // <----------------------------- 
    } 

    public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name, XmlDictionaryString ns, IList<Type> knownTypes) 
    { 
     return new DataContractSerializer(type, name, ns, knownTypes, 
      _maxItemsInObjectGraph, 
      _ignoreExtensionDataObject, 
      true, 
      null /*dataContractSurrogate*/, 
      DataContractResolver); // <----------------------------- 
    } 
} 
Các vấn đề liên quan