与大多数人一样,当将(可怕的)EF对象序列化为JSON时,我也遇到了循环引用错误的问题。执行db.Detach(efObject)有帮助 - 但我仍然像“EntityKey”那样输出垃圾。
所以我想知道是否有一个选项(通过JsConfig?)告诉序列化器通过名称(EntityKey)或类型(EntityReference< T>或EntityCollection< T>)忽略属性?
或者我将被迫完全抛弃EF并切换到更好的东西(我不想手动定义ORM类 - 我希望它们是从DB自动生成的)?
答案 0 :(得分:3)
您不应该尝试重复使用Entity Framework types as DTO's,因为它们是设计不良的DTO替代品。您应该使用ServiceStack的内置TranslateTo / PopulateFrom映射器(或AutoMapper)将它们映射到特殊用途的DTO类型并返回它们。
话虽如此,请对要序列化的属性使用IgnoreDataMember or specify DataMembers。
答案 1 :(得分:1)
免责声明:我目前正在进行原型设计,对我来说,便利性不仅仅是解决方案的稳健性。所以,我所做的并不是一个好方法 - 我在这里复制粘贴它,以防万一其他人处于相同的位置,并想要一个简单的(不是最好的)出路。你已被警告过了。
我认为您已经在MVC项目中使用ServiceStack.Text。如果情况并非如此,请按照此质量检查中的说明进行操作:ASP.NET MVC Json DateTime Serialization conversion to UTC
查看ServiceStack.Text library from GitHub并(当然)在您的MVC项目中引用它而不是DLL。
将此添加到ServiceStack.Text / JsConfig类:
// Added properties for global excluding
public static Type[] GlobalExcludedBaseTypes;
public static string[] GlobalExcludedProperties;
在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();
}
在Global.asax中添加以下两行:
JsConfig.GlobalExcludedProperties = new[] { "EntityKey", "EntityState" };
JsConfig.GlobalExcludedBaseTypes = new[] { typeof(RelatedEnd), typeof(EntityReference) };
就是这样 - EntityState&amp; EntityKey将不再被序列化,您将不再需要担心循环依赖。
但是,再次 - 这不是最佳实践 - 只要您稳定解决方案,请务必遵循mythz推荐的内容并向DTO迁移。
答案 2 :(得分:0)
您可以在模型上使用ScriptIgnore属性:
public class Item
{
[ScriptIgnore]
public Item ParentItem { get; set; }
}