在“System.Data.Entity.Spatial.DbGeography 上从 'WellKnownValue' 获取值时出错
Error getting value from 'WellKnownValue' on 'System.Data.Entity.Spatial.DbGeography
我在 SinglePageApplication 中使用 DbGeography-Type(使用 breeze 和 angular)。现在,将数据与 DbGeography-Type(只读)一起使用时没有问题。
一旦我保存了 属性 为 DbGeography-Type 的实体,我就会收到以下错误:
Error getting value from 'WellKnownValue' on 'System.Data.Entity.Spatial.DbGeography'
当数据序列化为 JSON(使用 newtonsoft JSON.NET 还是 ODATA/WebAPI?)时,DbGeography 被正确序列化,但 属性 "WellKownValue" 称为 "Geography"。这也反映在 MSDN-Documentation:
[DataMemberAttribute(Name = "Geography")]
public DbGeographyWellKnownValue WellKnownValue { get; set; }
我的实体看起来像这样(通过网络):
{
..
"Name" : "Test",
"Coordinate" : {
"$id" : "3",
"$type" : "System.Data.Entity.Spatial.DbGeography, EntityFramework",
"Geography" : {
"$id" : "4",
"$type" : "System.Data.Entity.Spatial.DbGeographyWellKnownValue, EntityFramework",
"CoordinateSystemId" : 4326,
"WellKnownText" : "POINT (8.73275400148029 47.5006958431132)"
}
}
}
我想稍后反序列化时,JSON.NET 不知道我的 [=50= 的 Geography-属性 ] 实际上称为 WellKnownValue.
我正在使用 Newtonsoft。Json-Package 7.0.1 版和 Microsoft.Data.OData 5.6.4 版。
如何解决这个问题?
我发现(使用 .NET Reflector)DbGeography-Type 可以由默认构造函数(不带参数)实例化但是这个默认构造函数没有设置一些重要的私有成员(如 _spatialProvider)。
当在反序列化期间调用 WellKnownValue-Getter 时,这会导致 NullReferenceException。所以我所做的是很多人以前必须做的(我希望不必做)——我创建了一个自定义 JsonConverter.
一个特点是,我必须在 BreezeWebApiConfig 中注册它,而不是正常的 WebApiConfig:
public class MyBreezeConfig : Breeze.ContextProvider.BreezeConfig
{
protected override JsonSerializerSettings CreateJsonSerializerSettings()
{
JsonSerializerSettings result = base.CreateJsonSerializerSettings();
result.Converters.Add(new WebDbGeographyJsonConverter());
return result;
}
}
和转换器:
public class WebDbGeographyJsonConverter : JsonConverter {
public override bool CanConvert(Type objectType) {
return typeof(DbGeography).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
var jObj = JObject.Load(reader);
if (jObj != null) {
var geography = jObj["Geography"];
if (geography != null) {
var wktText = geography["WellKnownText"].Value<string>();
if (!string.IsNullOrEmpty(wktText)) {
var coordSysId = geography["CoordinateSystemId"].Value<int?>() ?? DbGeography.DefaultCoordinateSystemId;
return DbGeography.FromText(wktText, coordSysId);
}
}
}
return null;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
throw new NotImplementedException();
}
public override bool CanWrite {
get {
// use default implementation of Serialization
return false;
}
}
}
我在 SinglePageApplication 中使用 DbGeography-Type(使用 breeze 和 angular)。现在,将数据与 DbGeography-Type(只读)一起使用时没有问题。
一旦我保存了 属性 为 DbGeography-Type 的实体,我就会收到以下错误:
Error getting value from 'WellKnownValue' on 'System.Data.Entity.Spatial.DbGeography'
当数据序列化为 JSON(使用 newtonsoft JSON.NET 还是 ODATA/WebAPI?)时,DbGeography 被正确序列化,但 属性 "WellKownValue" 称为 "Geography"。这也反映在 MSDN-Documentation:
[DataMemberAttribute(Name = "Geography")]
public DbGeographyWellKnownValue WellKnownValue { get; set; }
我的实体看起来像这样(通过网络):
{
..
"Name" : "Test",
"Coordinate" : {
"$id" : "3",
"$type" : "System.Data.Entity.Spatial.DbGeography, EntityFramework",
"Geography" : {
"$id" : "4",
"$type" : "System.Data.Entity.Spatial.DbGeographyWellKnownValue, EntityFramework",
"CoordinateSystemId" : 4326,
"WellKnownText" : "POINT (8.73275400148029 47.5006958431132)"
}
}
}
我想稍后反序列化时,JSON.NET 不知道我的 [=50= 的 Geography-属性 ] 实际上称为 WellKnownValue.
我正在使用 Newtonsoft。Json-Package 7.0.1 版和 Microsoft.Data.OData 5.6.4 版。
如何解决这个问题?
我发现(使用 .NET Reflector)DbGeography-Type 可以由默认构造函数(不带参数)实例化但是这个默认构造函数没有设置一些重要的私有成员(如 _spatialProvider)。
当在反序列化期间调用 WellKnownValue-Getter 时,这会导致 NullReferenceException。所以我所做的是很多人以前必须做的(我希望不必做)——我创建了一个自定义 JsonConverter.
一个特点是,我必须在 BreezeWebApiConfig 中注册它,而不是正常的 WebApiConfig:
public class MyBreezeConfig : Breeze.ContextProvider.BreezeConfig
{
protected override JsonSerializerSettings CreateJsonSerializerSettings()
{
JsonSerializerSettings result = base.CreateJsonSerializerSettings();
result.Converters.Add(new WebDbGeographyJsonConverter());
return result;
}
}
和转换器:
public class WebDbGeographyJsonConverter : JsonConverter {
public override bool CanConvert(Type objectType) {
return typeof(DbGeography).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
var jObj = JObject.Load(reader);
if (jObj != null) {
var geography = jObj["Geography"];
if (geography != null) {
var wktText = geography["WellKnownText"].Value<string>();
if (!string.IsNullOrEmpty(wktText)) {
var coordSysId = geography["CoordinateSystemId"].Value<int?>() ?? DbGeography.DefaultCoordinateSystemId;
return DbGeography.FromText(wktText, coordSysId);
}
}
}
return null;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
throw new NotImplementedException();
}
public override bool CanWrite {
get {
// use default implementation of Serialization
return false;
}
}
}