目前我使用[JsonIgnore]
属性来避免模型中的循环引用。但我认为,它将适用于所有实现。
现在我正在使用这个 -
我有两个型号:
public class Project
{
public int ProjectID { get; set; }
[Required]
public string ProjectName { get; set; }
public DateTime? EstimatedEndDate { get; set; }
public DateTime? ProjectStartDate { get; set; }
public string OrderNumber { get; set; }
public string ProjectDescription { get; set; }
public virtual List<ServiceObject> ServiceObjects { get; set; }
[Required]
public string RegardingUser { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedDate { get; set; }
public string ModifiedBy { get; set; }
public DateTime ModifiedDate { get; set; }
public bool IsProjectDeleted { get; set; }
[NotMapped]
public int? ServiceObjectTemplateID { get; set; }
}
另一个模型是 -
public class ServiceObject
{
public int ServiceObjectID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string RegardingUser { get; set; }
public int? ParentServiceObjectID { get; set; }
[ForeignKey("ParentServiceObjectID")]
public virtual List<ServiceObject> ServiceObjects { get; set; }
public int ProjectID { get; set; }
[JsonIgnore]
public virtual Project Project { get; set; }<---------------------------
public virtual List<ServicePicture> ServicePictures { get; set; }
public bool IsServiceObjectDeleted { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedDate { get; set; }
public string ModifiedBy { get; set; }
public DateTime ModifiedDate { get; set; }
}
但是我想在Linq中将JsonIgnore
属性或任何其他属性应用于Sql查询本身。我的意思是我想动态应用它。
查询就像 -
var projectList = (from pro in context.Projects.All
select pro).ToList();
我想有条件地申请。
提前致谢。
答案 0 :(得分:3)
XY问题。你的实际问题是&#34;我想在运行时控制哪些属性被序列化&#34;。
控制序列化属性的最常用方法是使用JsonIgnoreAttribute
。但是正如其他人所评论的那样,属性是在编译时应用的,通常不能在运行时修改(也不是你想要的,因为它实际上是在运行时更改的全局设置,你会遇到大量的线程问题)。
相反,答案是使用IContractResolver
接口来更改序列化行为。
public class OmitPropertyContractResolver
: IContractResolver
{
private readonly string[] _ignoredProperties;
private readonly IContractResolver _resolver;
public OmitPropertyContractResolver(IContractResolver resolver, params string[] ignoredProperties)
{
_ignoredProperties = ignoredProperties;
_resolver = resolver;
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var properties = _resolver.CreateProperties(type, memberSerialization);
return properties
.Where(p => _ignoredProperties.Contains(p.Name) == false)
.ToList();
}
}
另一种可能性是在Json.net设置中使用ReferenceLoopHandling
设置。
var serializer = new JsonSerializer(
new JsonSerializerSetting()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
} );
这将仅对每个对象进行一次序列化。
最后一个选项是使用ItemReferenceLoopHandling
。这是一种序列化(和反序列化)具有循环引用的对象图(注释,图形而非树)的非标准方法。
这种方法的缺点是它是非标准的,可能无法在客户端工作。
答案 1 :(得分:2)
好的,基于您的输入并且我怀疑,您所看到的是典型的EF Code First问题。 EF为您的每个实体生成动态代理,以便它可以跟踪对它的更改。但是,这会使序列化变得困难,因为它们被创建为dynamic
个对象。有几种方法可以避免这种情况:
选项A:仅为特定查询禁用代理创建:
// disable proxy creation just for the duration of query
context.Configuration.ProxyCreationEnabled = false;
// do the query, serialize, go crazy!
// enable proxy again. or if your context goes out of scope after this call, then you can ignore re-enabling.
context.Configuration.ProxyCreationEnabled = true;
选项B:如果您稍后不打算修改和更新实体
var entity = context.Where(...); // or whatever query
// detach entity
context.Entry(entity).State = EntityState.Detached;
选项C:通过修改类型定义来避免代理:
如果创建没有虚拟属性的密封类型或类型,EF将不会创建代理 代理人没什么可做的。
public sealed class Project {...}
// or make it non virtual
...
public List<ServiceObject> ServiceObjects { get; set; }
...
注意在这种情况下,您必须手动加载相关对象:
context.Projects.Include(p => p.ServiceObjects).ToList();
选项D:永久禁用代理创建:
// in your initializer or DbContext class' constructor
DbContext.Configuration.ProxyCreationEnabled = false;
注意:如果禁用了代理创建,则EF不会自动跟踪更改。您可以使用快照方法manually track them。
您可以根据自己的设计选择其中一个或多个选项。我通常坚持使用选项A或B.