2

私はそうではないと確信していますが、この質問がすでに尋ねられている場合はお詫び申し上げます。これがばかげた質問である場合は、さらにお詫び申し上げますが、何かが完全に欠けているか、正しい考えを持っていて、自分の正気のためにバックアップが必要なように感じます。

アプリケーションに WCF Data Services 5.0 を実装してきましたが、エンティティ オブジェクトを返す読み取り操作に問題はありません。

残念ながら、サービス操作に関しては、プリミティブ型しか返せないという厄介な制限があります ( MSDN を参照)。エンティティ オブジェクトに問題がないことを考えると、非常に面倒です。

WCFDS はそれを認識するため、「ダミー」の複合型を作成することが 1 つの回避策であることはわかっていますが、実際にはデータベースにないデータ モデルにランダムな POCO をスローしたくありません。

そのため、私が思いついた解決策は、サービスによって返される JSON 文字列にシリアル化できるオブジェクトの拡張メソッドを作成することでした。私の質問は; なぜ私がこれをすべきではないか、または誰かがより良い代替案を提案できる理由はありますか?


編集:現在の問題を明確にするための追加情報

私がやっていることの非常に簡単な例を作成しましたが、それはもともとこの質問を提起しました。私のサービスクラスは最初に続きます:

[JsonpSupportBehavior]
public partial class SchedulingService : DataService<ChronosDataContext>, ISchedulingService
{
    public static void InitializeService(DataServiceConfiguration config)
    {
        #if DEBUG
        config.UseVerboseErrors = true;
        #endif

        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;

        config.SetServiceOperationAccessRule(
        "TestService",
        ServiceOperationRights.All);
    }

    [WebGet]
    public SchedulingResult TestService(
         string testParam1,
         string testParam2)
    {
         // NOTE: I never use the params, they're just there for this example.
         SchedulingResult result = SchedulingResult.Empty;

         result.Status = OperationStatus.Success;
         result.ResponseID = Guid.NewGuid();
         result.AffectedIDs = new List<int>(new int[] { 1, 2, 3, 4, 5, 6, 7 });
         result.RecordsAffected = 10;

         return result;
    }
}

ブラウザを使用してこのサービスにアクセスしようとすると、次のリクエスト エラーが発生します。

The server encountered an error processing the request. The exception message is 
'Unable to load metadata for return type 
    'Chronos.Services.SchedulingResult' of method 
    'Chronos.Services.SchedulingResult TestService(System.String, System.String)'.'. 
See server logs for more details. 

The exception stack trace is:
at System.Data.Services.Providers.BaseServiceProvider.AddServiceOperation(MethodInfo method, String protocolMethod) 
at System.Data.Services.Providers.BaseServiceProvider.AddOperationsFromType(Type type) 
at System.Data.Services.Providers.BaseServiceProvider.LoadMetadata() 
at System.Data.Services.DataService`1.CreateMetadataAndQueryProviders(IDataServiceMetadataProvider& metadataProviderInstance, IDataServiceQueryProvider& queryProviderInstance, BaseServiceProvider& builtInProvider, Object& dataSourceInstance) 
at System.Data.Services.DataService`1.CreateProvider() 
at System.Data.Services.DataService`1.HandleRequest() 
at System.Data.Services.DataService`1.ProcessRequestForMessage(Stream messageBody) 
at SyncInvokeProcessRequestForMessage(Object , Object[] , Object[] ) 
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs) 
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) 
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc) 
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc& rpc) 
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc) 
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc) 
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc) 
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc) 
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc) 
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc) 
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)

以下は、返そうとしている SchedulingResult を構成するクラスです。

public class SchedulingResult : ServiceInvocationResponse
{
    public SchedulingResult()
        : base()
    {
        this.Payload = new object[] 
        {
            new List<int>(),
            new List<int>()
        };
    }

    public List<int> AffectedIDs 
    {
        get { return (List<int>)Payload[0]; }
        set { Payload[0] = value; }
    }

    public List<int> FailedIDs
    {
        get { return (List<int>)Payload[1]; }
        set { Payload[1] = value; }
    }

    public static SchedulingResult Empty
    {
        get { return new SchedulingResult(); }
    }
}

public class ServiceInvocationResponse : AbstractJsonObject<ServiceInvocationResponse>
{
    public ServiceInvocationResponse()
    {
        this.Status = OperationStatus.Unknown;
        this.Severity = ErrorSeverity.None;
    }

    public virtual int RecordsAffected { get; set; }

    public virtual Exception ErrorObject { get; set; }

    internal virtual object[] Payload { get; set; }
}


public abstract class AbstractJsonObject<TBaseType>
{
    public virtual object Deserialize(string source)
    {
        return JsonConvert.DeserializeObject(source);
    }

    public virtual T Deserialize<T>(string source)
    {
        return JsonConvert.DeserializeObject<T>(source);
    }

    public string Serialize()
    {
        return JsonConvert.SerializeObject(
            this, Formatting.Indented);
    }

    public override string ToString()
    {
        return this.Serialize();
    }

    public static TBaseType FromString(string json)
    {
        return JsonConvert.DeserializeObject<TBaseType>(json);
    }
}
4

1 に答える 1

3

サービス操作から、1 つまたは複数のプリミティブ、複合、またはエンティティ タイプを返すことができます。

  • プリミティブ型は、文字列、int、bool など、あなたが期待するものです。
  • ID複合型は、一意のキー (名前付きプロパティまたは[DataServiceKey("<yourkeyhere>")]属性)を持たないクラスです。
  • エンティティ タイプは、一意のキーを持つクラスです

例えば:

using System.Data.Services;
using System.Data.Services.Common;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace Scratch.Web
{
    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
    public class ScratchService : DataService<ScratchContext>
    {
        public static void InitializeService(DataServiceConfiguration config)
        {
            config.SetEntitySetAccessRule("*", EntitySetRights.All);
            config.SetServiceOperationAccessRule("*", ServiceOperationRights.AllRead);
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
            config.UseVerboseErrors = true;
        }

        [WebGet]
        public string GetPrimitive()
        {
            return "Success";
        }

        [WebGet]
        public IQueryable<string> GetPrimitives()
        {
            return new[] { "Success", "Hello World" }.AsQueryable();
        }

        [WebGet]
        public ComplexType GetComplexType()
        {
            return new ComplexType { Property1 = "Success", Property2 = "Hello World" };
        }

        [WebGet]
        public IQueryable<ComplexType> GetComplexTypes()
        {
            return new[] {
                           new ComplexType { Property1 = "Success", Property2 = "Hello World" },
                           new ComplexType { Property1 = "Success", Property2 = "Hello World" }
                       }.AsQueryable();
        }

        [WebGet]
        public EntityType GetEntityType()
        {
            return new EntityType { Property1 = "Success", Property2 = "Hello World" };
        }

        [WebGet]
        public IQueryable<EntityType> GetEntityTypes()
        {
            return new[] {
                           new EntityType { Property1 = "Success1", Property2 = "Hello World" },
                           new EntityType { Property1 = "Success2", Property2 = "Hello World" }
                       }.AsQueryable();
        }
    }

    public class ScratchContext { }

    public class ComplexType
    {
        public string Property1 { get; set; }
        public string Property2 { get; set; }
    }

    [DataServiceKey("Property1")]
    public class EntityType
    {
        public string Property1 { get; set; }
        public string Property2 { get; set; }
    }
}

もしかして、何か他の問題に遭遇していませんか?

于 2012-07-12T17:56:03.550 に答える