从 C# WCF 服务返回具有动态维数的交错数组

发布于 2024-11-01 02:00:11 字数 821 浏览 0 评论 0原文

我目前正在尝试创建一个服务,该服务将返回 C#/WCF 数据服务中 OLAP 多维数据集查询的结果。我这样做是为了获得对 OLAP 结果如何序列化、客户端如何进行身份验证/授权以及能够直接从网站中的 javascript 查询多维数据集的完整编程控制。

OLAP 查询的结果可能具有任意数量的维度(实际上最大介于 1 到 5 之间)。我遇到的问题是,我无法弄清楚如何首先创建动态维数的锯齿状数组,而不对我可能使用的每个维数的处理进行硬编码。所以第一个任务是:是否有一种优雅的方式在 C# 中创建动态维数的锯齿状数组?

一旦我有了这个动态维数数组,是否可以使用 DataContractJsonSerializer(或任何其他免费提供的 json 序列化器)将其序列化为 json。目标是将其序列化为一个类似于二维结果的对象:

{
  "DimensionMemberCaptions" = [["Dim1 member1", "Dim2 member2"], ["Dim2 member1"], ["Dim2 member2"]],
  "Data" = [[1, 2],
            [3, 4]],
  "FormatedData = [["1$", "2$"],
                   ["3$", "4$"]]
}

其中 DimensionMemberCaptions 包含每个维度的标题(OLAP 成员名称),而 data/formateddata 是结果表。

我想避免编写自己的序列化函数,但随着时间的推移,它似乎更有吸引力——使用数组(多维数组而不是锯齿状数组)并编写我自己的 json 序列化程序,专门用于将 OLAP 输出序列化到流由 WCF REST 方法返回。

I'm currently trying create a service that will return results of a OLAP cube query in a C#/ WCF data service. I am doing this to gain complete programmatic control over how the OLAP results are serialized, how clients are authenticated/authorized and to be able to query cubes from javascript in a website directly.

The results from the OLAP queries may have any number of dimensions (realistically somewhere between 1 and 5 max). The problem I'm having is that I cannot figure out how to first create a jagged array of a dynamic number of dimensions without hard codding the handling of every number of dimensions I'll possibly use. So the first quest is: is there an elegant way to create a jagged array of a dynamic number of dimensions in C#?

Once I have this array of dynamic number of dimensions, is it possible to then serialize this into json using DataContractJsonSerializer (or any other json serializer freely available). The goal is to serialize this into an object that looks something like this for 2-dimensional results:

{
  "DimensionMemberCaptions" = [["Dim1 member1", "Dim2 member2"], ["Dim2 member1"], ["Dim2 member2"]],
  "Data" = [[1, 2],
            [3, 4]],
  "FormatedData = [["1$", "2$"],
                   ["3$", "4$"]]
}

Where DimensionMemberCaptions contain the headers for each dimension (OLAP member names) and data/formateddata is a table of the results.

I would like to avoid writing my own serialization functions but its seeming more appealing as time goes on -- using an Array (multi-dimensional array instead of jagged) and writing my own json serializer specifically for the purpose of serializing OLAP output to a Stream returned by a WCF REST method.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

玻璃人 2024-11-08 02:00:11

我找到了一种解决问题的方法,该方法比我指定的问题更具体地针对 Adomd,但我认为可以应用相同的技术来解决这个问题,而不依赖于 Adomd。我选择使用Newtonsoft的Json序列化库(http://james.newtonking.com/projects/ json-net.aspx)。有了这个,我可以创建自己的“JsonConverter”来序列化 Adomd CellSet(基本上是多维 OLAP 查询的结果)。无论维数有多少,这都将起作用。

public class CellSetConverter : JsonConverter
{

    public override bool CanRead
    {
        get
        {
            return false;
        }
    }

    public override bool CanConvert(Type objectType)
    {
        if (objectType == typeof(CellSet))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        CellSet cellSet = (CellSet)value;
        int cellCount = cellSet.Cells.Count;
        int[] axisCounts = new int[cellSet.Axes.Count];
        int[] currentIndex = new int[cellSet.Axes.Count];
        for (int i = 0; i < axisCounts.Length; i++)
        {
            axisCounts[i] = cellSet.Axes[i].Positions.Count;
        }

        for (int i = 0; i < cellSet.Axes.Count; i++)
        {
            writer.WriteStartArray();
        }

        for (int i = 0; i < cellCount; i++)
        {
            serializer.Serialize(writer, cellSet[currentIndex].Value);
            currentIndex = IncrementIndex(writer, currentIndex, axisCounts);
        }
    }

    string[] GetCaptions(CellSet cellSet, int[] index)
    {
        string[] captions = new string[index.Length];
        for (int i = 0; i < index.Length; i++)
        {
            Axis axis = cellSet.Axes[i];
            captions[i] = axis.Positions[index[i]].Members[0].Caption;
        }

        return captions;
    }

    int[] IncrementIndex(JsonWriter writer, int[] index, int[] maxSizes)
    {
        bool incremented = false;
        int currentAxis = 0;
        while (!incremented)
        {
            if (index[currentAxis] + 1 == maxSizes[currentAxis])
            {
                writer.WriteEndArray();
                index[currentAxis] = 0;
                currentAxis++;
            }
            else
            {
                for (int i = 0; i < currentAxis; i++)
                {
                    writer.WriteStartArray();
                }

                index[currentAxis]++;
                incremented = true;
            }

            if (currentAxis == index.Length)
            {
                return null;
            }
        }

        return index;
    }
}

以及与之配套的 WCF Rest 服务:

[ServiceContract]
public class MdxService
{
    const string JsonMimeType = "application/json";
    const string connectionString = "[Data Source String]";
    const string mdx = "[MDX query]";

    [OperationContract]
    [WebGet(UriTemplate = "OlapResults?session={session}&sequence={sequence}")]
    public Stream GetResults(string session, string sequence)
    {
        CellSet cellSet;
        using (AdomdConnection connection = new AdomdConnection(connectionString))
        {
            connection.Open();
            AdomdCommand command = connection.CreateCommand();
            command.CommandText = mdx;
            cellSet = command.ExecuteCellSet();
        }

        string result = JsonConvert.SerializeObject(cellSet, new CellSetConverter());
        WebOperationContext.Current.OutgoingResponse.ContentType = JsonMimeType;
        Encoding encoding = Encoding.UTF8;
        byte[] bytes = encoding.GetBytes(result);
        return new MemoryStream(bytes);
    }
}

I found a way to solve my problem thats more specific to Adomd than my question specified, but I think the same technique could be applied to solve this without a dependency on Adomd. I choose to use Newtonsoft's Json serialization library (http://james.newtonking.com/projects/json-net.aspx). With this I could create my own 'JsonConverter' to serialize a Adomd CellSet (basically the results from a mulitdimensional OLAP query). This will work regardless of the number of dimensions.

public class CellSetConverter : JsonConverter
{

    public override bool CanRead
    {
        get
        {
            return false;
        }
    }

    public override bool CanConvert(Type objectType)
    {
        if (objectType == typeof(CellSet))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        CellSet cellSet = (CellSet)value;
        int cellCount = cellSet.Cells.Count;
        int[] axisCounts = new int[cellSet.Axes.Count];
        int[] currentIndex = new int[cellSet.Axes.Count];
        for (int i = 0; i < axisCounts.Length; i++)
        {
            axisCounts[i] = cellSet.Axes[i].Positions.Count;
        }

        for (int i = 0; i < cellSet.Axes.Count; i++)
        {
            writer.WriteStartArray();
        }

        for (int i = 0; i < cellCount; i++)
        {
            serializer.Serialize(writer, cellSet[currentIndex].Value);
            currentIndex = IncrementIndex(writer, currentIndex, axisCounts);
        }
    }

    string[] GetCaptions(CellSet cellSet, int[] index)
    {
        string[] captions = new string[index.Length];
        for (int i = 0; i < index.Length; i++)
        {
            Axis axis = cellSet.Axes[i];
            captions[i] = axis.Positions[index[i]].Members[0].Caption;
        }

        return captions;
    }

    int[] IncrementIndex(JsonWriter writer, int[] index, int[] maxSizes)
    {
        bool incremented = false;
        int currentAxis = 0;
        while (!incremented)
        {
            if (index[currentAxis] + 1 == maxSizes[currentAxis])
            {
                writer.WriteEndArray();
                index[currentAxis] = 0;
                currentAxis++;
            }
            else
            {
                for (int i = 0; i < currentAxis; i++)
                {
                    writer.WriteStartArray();
                }

                index[currentAxis]++;
                incremented = true;
            }

            if (currentAxis == index.Length)
            {
                return null;
            }
        }

        return index;
    }
}

And the WCF Rest service to go with it:

[ServiceContract]
public class MdxService
{
    const string JsonMimeType = "application/json";
    const string connectionString = "[Data Source String]";
    const string mdx = "[MDX query]";

    [OperationContract]
    [WebGet(UriTemplate = "OlapResults?session={session}&sequence={sequence}")]
    public Stream GetResults(string session, string sequence)
    {
        CellSet cellSet;
        using (AdomdConnection connection = new AdomdConnection(connectionString))
        {
            connection.Open();
            AdomdCommand command = connection.CreateCommand();
            command.CommandText = mdx;
            cellSet = command.ExecuteCellSet();
        }

        string result = JsonConvert.SerializeObject(cellSet, new CellSetConverter());
        WebOperationContext.Current.OutgoingResponse.ContentType = JsonMimeType;
        Encoding encoding = Encoding.UTF8;
        byte[] bytes = encoding.GetBytes(result);
        return new MemoryStream(bytes);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文