从c# WCF服务返回一个具有动态维数的锯齿数组
本文关键字:动态 数组 一个 服务 WCF 返回 | 更新日期: 2023-09-27 17:50:14
我目前正在尝试创建一个服务,它将在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方法返回的流。
我找到了一种方法来解决我的问题,它比我的问题指定的更特定于addom,但我认为同样的技术可以应用于解决这个问题,而不依赖于addom。我选择使用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);
}
}