2014-06-06 21 views
6

在我的设计我有了其类型可以被继承属性的类:如何防止Json.NET使用Entity Framework代理类型名称?

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代理的类型名称而不是“真实”类型名称。因此,而不是:

$type: "System.Data.Entity.DynamicProxies.CsvSource_0B3579D9BE67D7EE83EEBDDBFA269439AFC6E1122A59B4BB81EB1F0147C7EE12" 

这是毫无意义的其他客户,我想获得:

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

达到此目的的最佳方法是什么?

+2

是禁止使用/创建代理对象这个代码路径的选项? EF的只读/急切使用似乎并不需要它AFAICT? –

+0

避免代理生成(或通过将'ProxyCreationEnabled'设置为false来禁用它)可能是在某些情况下适用的一种策略。但是,在其他情况下,这是不适用的,我的问题仍然存在。 – Dejan

+1

[Serialization of Entity Framework objects with One to Many Relationship](http://stackoverflow.com/questions/13077328/serialization-of-entity-framework-objects-with-one-to-many-relationship) –

回答

4

你可以做两件事情:

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

  • 使用AsNoTracking()扩展方法,当你恢复你的实体,像这样:

    MyContext.MyTable.AsNoTracking(). // rest of the query here

这表明你不希望你的实体跟踪代理,所以你获得实体类。这与前述配置没有干扰。

+0

我想你是对的。尽管我可以设想Json.NET在序列化时简单地取代基类而不是代理。 – Dejan

+0

有没有人知道有关禁用代理生成的副作用的良好文档的参考? – Dejan

+0

在这里你有一个很好的解释:http://stackoverflow.com/questions/7111109/should-i-enable-or-disable-dynamic-proxies-with-entity-framework-4-1-and-mvc3 – JotaBe

4

不要求你更改您的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() }); 
相关问题