我正在使用 MVC3、Razor 视图引擎、带有工作单元的存储库模式以及使用 EF4.1 Code First 来定义我的数据模型来构建应用程序。
这里有一点背景(如果你愿意,可以涂上光泽)。
应用程序本身只是一个 Intranet '菜单'。
两个主要实体是 MenuItem 和 Department ,其中:
- MenuItem 可以有很多部门
- 部门可以有很多菜单项
- MenuItem 可能有一个 MenuItem 作为父项
这就是我定义我的实体的方式
public class MenuItem
{
public int MenuItemId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public virtual ICollection<Department> Departments { get; set; }
public int? ParentId { get; set; }
public virtual MenuItem ParentMenuItem { get; set; }
}
public class Department
{
public int DepartmentId { get; set; }
public string Name { get; set; }
public virtual ICollection<MenuItem> MenuItems { get; set; }
}
我正在使用 FluentAPI 为 MenuItem 定义自引用多对多。
我遇到的问题是通过 JSON 将 MenuItem 传递给视图。核心问题是我的实体之间有一个内置 JSON 解析器无法处理的循环引用,并且我仍然启用了延迟加载和代理生成。
我使用来自 Nuget 的 JSON.net 库作为我的 JSON 序列化器,因为这似乎是解决循环引用问题的好方法。我现在不确定如何“修复”代理生成问题。目前序列化程序抛出The RelationshipManager object could not be serialized. This type of object cannot be serialized when the RelationshipManager belongs to an entity object that does not implement IEntityWithRelationships.
谁能帮我这个?如果我关闭代理生成,我将有一段时间加载所有 MenuItem 子项,所以我很想保持这个状态。我已经阅读了相当多的内容,并且似乎有各种不同的答案,包括将实体投影到另一个对象中并对其进行序列化等等。理想情况下,有某种方法可以配置 JSON.net 以忽略 RelationshipManager 对象?
更新
这是我用作 JSON.Net 序列化程序的自定义 ContractResolver 的内容。这似乎解决了我的问题。
public class ContractResolver : DefaultContractResolver
{
private static readonly IEnumerable<Type> Types = GetEntityTypes();
private static IEnumerable<Type> GetEntityTypes()
{
var assembly = Assembly.GetAssembly(typeof (IEntity));
var types = assembly.GetTypes().Where(t => String.Equals(t.Namespace, "Namespace", StringComparison.Ordinal));
return types;
}
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
if (!AllowType(objectType))
return new List<MemberInfo>();
var members = base.GetSerializableMembers(objectType);
members.RemoveAll(memberInfo => (IsMemberEntityWrapper(memberInfo)));
return members;
}
private static bool AllowType(Type objectType)
{
return Types.Contains(objectType) || Types.Contains(objectType.BaseType);
}
private static bool IsMemberEntityWrapper(MemberInfo memberInfo)
{
return memberInfo.Name == "_entityWrapper";
}
}
IEntity
是我的所有 Code First 实体对象都实现的接口。