不要在JSON(ServiceStack.Text库)中序列化Entity Framework类引用

时间:2013-02-21 09:40:04

标签: asp.net-mvc json entity-framework servicestack

与大多数人一样,当将(可怕的)EF对象序列化为JSON时,我也遇到了循环引用错误的问题。执行db.Detach(efObject)有帮助 - 但我仍然像“EntityKey”那样输出垃圾。

所以我想知道是否有一个选项(通过JsConfig?)告诉序列化器通过名称(EntityKey)或类型(EntityReference< T>或EntityCollection< T>)忽略属性?

或者我将被迫完全抛弃EF并切换到更好的东西(我不想手动定义ORM类 - 我希望它们是从DB自动生成的)?

3 个答案:

答案 0 :(得分:3)

您不应该尝试重复使用Entity Framework types as DTO's,因为它们是设计不良的DTO替代品。您应该使用ServiceStack的内置TranslateTo / PopulateFrom映射器(或AutoMapper)将它们映射到特殊用途的DTO类型并返回它们。

话虽如此,请对要序列化的属性使用IgnoreDataMember or specify DataMembers

答案 1 :(得分:1)

免责声明:我目前正在进行原型设计,对我来说,便利性不仅仅是解决方案的稳健性。所以,我所做的并不是一个好方法 - 我在这里复制粘贴它,以防万一其他人处于相同的位置,并想要一个简单的(不是最好的)出路。你已被警告过了。

  1. 我认为您已经在MVC项目中使用ServiceStack.Text。如果情况并非如此,请按照此质量检查中的说明进行操作:ASP.NET MVC Json DateTime Serialization conversion to UTC

  2. 查看ServiceStack.Text library from GitHub并(当然)在您的MVC项目中引用它而不是DLL。

  3. 将此添加到ServiceStack.Text / JsConfig类:

    // Added properties for global excluding
    public static Type[] GlobalExcludedBaseTypes;
    public static string[] GlobalExcludedProperties;
    
  4. 在ServiceStack.Text / TypeConfig类中更改静态TypeConfig():

    static TypeConfig()
    {
        config = new TypeConfig(typeof(T));
    
        var excludedProperties = JsConfig<T>.ExcludePropertyNames ?? new string[0];
        var excludedGlobalBaseTypes = JsConfig.GlobalExcludedBaseTypes ?? new Type[0];
        var excludedGlobalProperties = JsConfig.GlobalExcludedProperties ?? new string[0];
    
        IEnumerable<PropertyInfo> properties = null;
    
        if (excludedProperties.Any() || excludedGlobalBaseTypes.Any() || excludedGlobalProperties.Any())
        {
            properties = config.Type.GetSerializableProperties().
                Where(x => !excludedProperties.Contains(x.Name) && !excludedGlobalProperties.Contains(x.Name) && !excludedGlobalBaseTypes.Contains(x.PropertyType.BaseType));
        }
        else
        {
            properties = config.Type.GetSerializableProperties();
        }
    
        Properties = properties.Where(x => x.GetIndexParameters().Length == 0).ToArray();
        Fields = config.Type.GetSerializableFields().ToArray();
    }
    
  5. 在Global.asax中添加以下两行:

    JsConfig.GlobalExcludedProperties = new[] { "EntityKey", "EntityState" };
    JsConfig.GlobalExcludedBaseTypes = new[] { typeof(RelatedEnd), typeof(EntityReference) };
    
  6. 就是这样 - EntityState&amp; EntityKey将不再被序列化,您将不再需要担心循环依赖。

    但是,再次 - 这不是最佳实践 - 只要您稳定解决方案,请务必遵循mythz推荐的内容并向DTO迁移。

答案 2 :(得分:0)

您可以在模型上使用ScriptIgnore属性:

public class Item
{
    [ScriptIgnore]
    public Item ParentItem { get; set; }
}