Entity framework 如何防止Json.NET使用实体框架代理类型名称?

Entity framework 如何防止Json.NET使用实体框架代理类型名称?,entity-framework,json.net,Entity Framework,Json.net,在我的设计中,我有一个类,它有一个属性,其类型可以继承自: public class Feed { ... [JsonProperty(TypeNameHandling = TypeNameHandling.Auto)] public FeedSource Source { get; set; } ... } public abstract class FeedSource { ... } public class CsvSource : FeedSource

在我的设计中,我有一个类,它有一个属性,其类型可以继承自:

public class Feed
{
    ...
    [JsonProperty(TypeNameHandling = TypeNameHandling.Auto)]
    public FeedSource Source { get; set; }
    ...
}

public abstract class FeedSource { ... }

public class CsvSource : FeedSource { ... }

public class DbSource : FeedSource { ... }
我使用实体框架将这个对象加载并存储到数据库中,并使用Json.NET将这个对象序列化为Json,以便进一步处理

我偶然发现的问题是,
$type
属性包含EF代理的typename,而不是“real”typename。因此,不是:

$type: "System.Data.Entity.DynamicProxies.CsvSource_0B3579D9BE67D7EE83EEBDDBFA269439AFC6E1122A59B4BB81EB1F0147C7EE12"
这对其他客户来说毫无意义,我想得到:

$type: "MyNamespace.CsvSource"
在我的JSON中

实现这一目标的最佳方法是什么?

您可以做两件事:

  • 通过将
    ProxyCreationEnabled
    设置为false,禁用跟踪代理。您可以在上下文的
    配置
    属性中找到此属性。如果为单个
    GetXxx
    方法使用上下文,则可以在不干扰其他上下文实例的情况下执行此操作

  • 恢复实体时使用
    AsNoTracking()
    扩展方法,如下所示:

    MyContext.MyTable.AsNoTracking()。//此处查询的其余部分


这表明您不需要实体的跟踪代理,因此您将获得实体类。这不会干扰上述配置。

另一种不需要您更改EF配置的方法是使用自定义SerializationBinder,例如:

class EntityFrameworkSerializationBinder : SerializationBinder
{
    public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
    {
        assemblyName = null;

        if (serializedType.Namespace == "System.Data.Entity.DynamicProxies")
            typeName = serializedType.BaseType.FullName;
        else
            typeName = serializedType.FullName;
    }

    public override Type BindToType(string assemblyName, string typeName)
    {
        throw new NotImplementedException();
    }
}
用法:

string json = JsonConvert.SerializeObject(entityFrameworkObject, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All, Binder = new EntityFrameworkSerializationBinder() });

禁用代理对象的使用/创建是否是此代码路径的选项?EF的只读/即时加载使用似乎并不需要它?避免代理生成(或通过将
ProxyCreationEnabled
设置为false来禁用它)可能是一种适用于某些情况的策略。然而,在其他情况下,这是不适用的,我的问题仍然悬而未决;看看这个:我想你是对的。尽管我可以想象Json.NET在序列化时只使用基类而不是代理。有人知道关于禁用代理生成的副作用的好文档的参考吗?这里有一个很好的解释:我也有同样的问题,但它的行为很奇怪。。仅xml序列化无法处理动态代理,但json序列化工作正常。。有什么想法吗?请提出一个新问题,再解释清楚一点。XML和JSON序列化程序的行为和配置不同,因此这可能是一个不同的问题。如果你这样做了,请告诉我,我会尽力帮助你。虽然功能正常,但我建议尝试这种方法的人使用这种方法进行一些性能测量。我发现它非常慢。@NateJackson在这里的测试表明,使用和不使用粘合剂的性能差异可以忽略不计。我怀疑问题在于EF。是否在数据上下文上启用了延迟加载?如果是,序列化过程可能会触发到数据库的往返,这反过来会导致极低的性能。尝试禁用延迟加载,并在序列化之前使用
Include()
获取相关数据。这应该是正确答案!——关闭有用的EF功能是愚蠢的,因为我们可以纠正不想要的行为。