private static Dictionary servers = new Dictionary();
最后,内存中会根据MongodbServerUrl也就是集群来保存每一个集群的信息:
[DataContract(Namespace = "Adhesive.Mongodb")]
public class ServerInfo
{
[DataMember]
public MongodbServerUrl Url { get; set; }
[DataMember]
public List Databases { get; set; }
[DataMember]
public List Descriptions { get; set; }
}
[DataContract(Namespace = "Adhesive.Mongodb")]
public class DatabaseStatus
{
[DataMember]
public double AverageObjectSize { get; set; }
[DataMember]
public int CollectionCount { get; set; }
[DataMember]
public long DataSize { get; set; }
[DataMember]
public int ExtentCount { get; set; }
[DataMember]
public long FileSize { get; set; }
[DataMember]
public int IndexCount { get; set; }
[DataMember]
public long IndexSize { get; set; }
[DataMember]
public long ObjectCount { get; set; }
[DataMember]
public long StorageSize { get; set; }
}
而后者是一个数据库下的集合信息:
[DataContract(Namespace = "Adhesive.Mongodb")]
public class CollectionInfo
{
[DataMember]
public string CollectionName { get; set; }
[DataMember]
public CollectionStatus CollectionStatus { get; set; }
[DataMember]
public List TextboxFilterColumns { get; set; }
[DataMember]
public List ListFilterColumns { get; set; }
[DataMember]
public List CascadeFilterColumns { get; set; }
}
[DataContract(Namespace = "Adhesive.Mongodb")]
public class CollectionStatus
{
[DataMember]
public DateTime LastEnsureIndexTime { get; set; }
[DataMember]
public double AverageObjectSize { get; set; }
[DataMember]
public long DataSize { get; set; }
[DataMember]
public int ExtentCount { get; set; }
[DataMember]
public int Flags { get; set; }
[DataMember]
public int IndexCount { get; set; }
[DataMember]
public List IndexStatusList { get; set; }
[DataMember]
public long LastExtentSize { get; set; }
[DataMember]
public string Namespace { get; set; }
[DataMember]
public long ObjectCount { get; set; }
[DataMember]
public double PaddingFactor { get; set; }
[DataMember]
public long StorageSize { get; set; }
[DataMember]
public long TotalIndexSize { get; set; }
}
每一个集合下都有若干索引,因此这里还有索引状态:
[DataContract(Namespace = "Adhesive.Mongodb")]
public class IndexStatus
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string Namespace { get; set; }
[DataMember]
public long Size { get; set; }
}
回到三种过滤列信息的定义:
[DataContract(Namespace = "Adhesive.Mongodb")]
public class TextboxFilterColumnInfo
{
[DataMember]
public string ColumnName { get; set; }
}
[DataContract(Namespace = "Adhesive.Mongodb")]
public class ListFilterColumnInfo
{
[DataMember]
public string ColumnName { get; set; }
[DataMember]
public List DistinctValues { get; set; }
}
[DataContract(Namespace = "Adhesive.Mongodb")]
public class CascadeFilterColumnInfo
{
[DataMember]
public string ColumnName { get; set; }
[DataMember]
public List DistinctValues { get; set; }
}
[DataContract(Namespace = "Adhesive.Mongodb")]
[Serializable]
public class ItemPair
{
[DataMember]
public string Name { get; set; }
[DataMember]
public object Value { get; set; }
}
public List GetTableData(string databasePrefix, List tableNames, DateTime beginTime, DateTime endTime, int pageIndex, int pageSize, Dictionary filters)
private void InternalGetDetailData(string prefix, List data, BsonElement element, List descriptions, List enumDescriptions, string pkColumnName)
{
try
{
if (element.Value.IsObjectId || element.Value.IsBsonNull) return;
var columnName = string.IsNullOrEmpty(prefix) ? element.Name : string.Format("{0}.{1}", prefix, element.Name);
var entityColumnName = columnName;
if (columnName.Contains("__") && columnName.Contains(".") && columnName.Split('.').Length > 2)
{
var parts = columnName.Split('.');
entityColumnName = "";
foreach (var part in parts)
{
if (part.IndexOf("__") >= 0)
entityColumnName += part.Substring(0, part.IndexOf("__"));
else
entityColumnName += part;
entityColumnName += ".";
}
entityColumnName = entityColumnName.TrimEnd('.');
}
var description = descriptions.SingleOrDefault(d => d.ColumnName == entityColumnName) ?? new MongodbColumnDescription
{
Description = "",
DisplayName = entityColumnName,
ColumnName = entityColumnName,
};
if (element.Value.IsBsonDocument)
{
var subData = new List();
foreach (var subDocument in element.Value.AsBsonDocument.Elements)
{
InternalGetDetailData(columnName, subData, subDocument, descriptions, enumDescriptions, pkColumnName);
}
data.Add(new Detail
{
Description = description.Description,
DisplayName = description.DisplayName.Replace('.', '_'),
ColumnName = columnName,
Value = "",
SubDetails = subData,
});
}
else
{
string value = "";
if (element.Value.IsBsonDateTime)
{
TimeZone ze = TimeZone.CurrentTimeZone;
value = (element.Value.AsDateTime + ze.GetUtcOffset(DateTime.Now)).ToString();
}
else
{
var enumColumnDescription = enumDescriptions.SingleOrDefault(e => e.Name == columnName);
if (enumColumnDescription == null)
{
value = element.Value.RawValue.ToString();
}
else
{
var enumValue = 0;
if (int.TryParse(element.Value.RawValue.ToString(), out enumValue) && enumColumnDescription.EnumItems.ContainsKey(enumValue.ToString()))
{
value = enumColumnDescription.EnumItems[enumValue.ToString()];
}
else
{
value = element.Value.RawValue.ToString();
}
}
}
var detail = new Detail
{
Description = description.Description,
DisplayName = description.DisplayName.Replace('.', '_'),
ColumnName = columnName,
Value = value,
};
data.Add(detail);
}
}
catch (Exception ex)
{
LocalLoggingService.Error(ex.ToString());
throw;
}
}
Detail的定义如下:
public class Detail
{
public string ColumnName { get; set; }
public string DisplayName { get; set; }
public string Description { get; set; }
public string Value { get; set; }
public List SubDetails { get; set; }
}
这很明显是一棵树。在这里我们要把元数据和实际数据进行对接,包括对枚举数据进行解析。
最后,还需要通过InternalGetTableData把树进一步进行转换成平面的数据:
if (detail.SubDetails != null)
{
foreach (var sub in detail.SubDetails)
{
var subdic = new Dictionary();
InternalGetTableData(sub, subdic);
foreach (var item in subdic)
{
row.Add(item.Key, item.Value);
}
}
}
else
{
row.Add(detail.DisplayName.Replace('.','_'), detail.Value == null ? "" : detail.Value.ToString());
}