【问题标题】:Error getting value from 'WellKnownValue' on 'System.Data.Entity.Spatial.DbGeography从“System.Data.Entity.Spatial.DbGeography”上的“WellKnownValue”获取值时出错
【发布时间】:2015-10-15 13:36:36
【问题描述】:

我在 SinglePageApplication 中使用 DbGeography-Type(带有微风和角度)。现在当使用带有 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 文档中:

https://msdn.microsoft.com/en-us/library/system.data.spatial.dbgeography.wellknownvalue(v=vs.110).aspx

[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 不知道我的对象的 Geography-Property 属性实际上称为 WellKnownValue。 p>

我使用的是 Newtonsoft.Json-Package 版本 7.0.1 和 Microsoft.Data.OData 版本 5.6.4。

如何解决这个问题?

【问题讨论】:

  • 那么DbGeographyWellKnownValue 是什么?当目的是序列化为 json 时,在 EF 中实现它而不是普通的 DbGeography 重要吗?
  • DbGeography 有一个名为WellKnownValue 的属性,其类型为DbGeographyWellKnownValue。一旦DbGeography 被序列化为 JSON,该属性在生成的 JSON 字符串中不再称为 WellKnownValue 而是 Geography(为什么我不知道)。但问题是:对于de序列化,必须能够使用默认构造函数(不带参数)实例化一个类。 DbGeography 类有这样一个构造函数,但没有设置一些重要的私有属性(请参阅我的答案),因此当您尝试读取属性 WellKnownValue(getter)时,您会收到错误消息。

标签: .net json.net deserialization breeze sqlgeography


【解决方案1】:

我发现(使用 .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;
        }
    }
}

【讨论】:

  • 什么是 WebDbGeography?只是一个常量持有者还是什么?
  • 是的。在我的示例中,我用常量替换了字符串。我在代码的其他部分也需要这些常量,因为我手动创建了微风元数据。
  • 谢谢。这就是我认为的,但我想确定一下。我非常感谢你说清楚。
猜你喜欢
  • 2019-11-10
  • 1970-01-01
  • 1970-01-01
  • 2014-07-13
  • 2016-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-01
相关资源
最近更新 更多