3

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

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

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

4

3 回答 3

3

您不应该尝试将实体框架类型重新用作 DTO,因为它们在设计上是 DTO 的不良替代品。相反,您应该使用 ServiceStack 的内置 TranslateTo/PopulateFrom 映射器(或 AutoMapper)将它们映射到特殊用途的 DTO 类型并返回它们。

话虽如此,请使用IgnoreDataMember 或在要序列化的属性上指定 DataMembers。

于 2013-02-21T15:31:19.560 回答
1

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

  1. 我假设您已经在 MVC 项目中使用了 ServiceStack.Text。如果不是这种情况,请按照以下 QA 的说明进行操作:ASP.NET MVC Json DateTime Serialization conversion to UTC

  2. 从 GitHub查看ServiceStack.Text 库,并且(当然)在您的 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) };
    

就是这样 - EntityState 和 EntityKey 将不再被序列化,您将不再需要担心循环依赖。

但是,再一次——这不是最佳实践——一旦你稳定了你的解决方案,一定要遵循 myz 的建议并迁移到 DTO。

于 2013-02-21T19:06:24.797 回答
0

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

public class Item
{
    [ScriptIgnore]
    public Item ParentItem { get; set; }
}
于 2013-02-21T10:18:31.810 回答