我一直在寻找如何避免返回不带属性 lazyLoader 的列表的方法,我想继续使用lazyLoader,但是当我返回整个列表时不希望返回该属性我的控制者提供的实体
我正在使用.NET core。
[
{
"lazyLoader": {},
"id": "id1"
"name": "name"
},
{
"lazyLoader": {},
"id": "id2",
"name": "name2"
}
]
答案 0 :(得分:1)
在Entity Framework中,如果您有一个对象的一个或多个属性使用延迟加载,请使用GetType()。Name检查其运行时类型名称。例如,对于 Car 类的对象,您会注意到运行时类型实际上是名为 CarProxy 的东西,这是由Entity Framework创建的临时内存类型。使用反射。该“伪”代理类的基本类型是 Car ,并具有所有原始的 Car 属性,但还包括一个名为 LazyLoader 的附加属性。可能需要它。
如果您进一步检查这种“伪造的” CarProxy 类型,您还将看到 Assembly.IsDynamic = true ,这表明该类是动态创建的使用反射(请参阅documentation):
var TheCar = DBContext.Cars.Find(1);
Console.WriteLine(TheCar.GetType().Assembly.IsDynamic.ToString()); //will echo "true"
幸运的是, Newtonsoft.Json 在 JsonConvert.SerializeObject()方法上有一个替代,该方法允许我们提供基本类型,因此生成的JSON不会包含该类型不存在的属性。因此,要消除 LazyLoader 属性,只需提供对象的BaseType作为类型参数即可:
var TheCar = DBContext.Cars.Find(1);
var TheJSON = Newtonsoft.Json.JsonConvert.SerializeObject(TheCar, TheCar.GetType().BaseType);
要确保序列化时没有任何循环引用循环(使用延迟加载的可能性很高),请使用以下设置调用序列化器:
var TheCar = DBContext.Cars.Find(1);
var Settings = new Newtonsoft.Json.JsonSerializerSettings
{
ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
};
var TheJSON = Newtonsoft.Json.JsonConvert.SerializeObject(TheCar, TheCar.GetType().BaseType, Settings);
注意:这可能仅在串行化器穿过对象时才在第一层深处起作用。如果您提供给序列化程序的对象还有更多的延迟加载子属性,则“ LazyLoader”属性可能会再次出现。我还没有测试过,所以不能确定。
答案 1 :(得分:1)
此问题的选中答案仅适用于根对象,如果我们有许多嵌套的延迟加载对象,则此解决方案将不起作用。 尽管@ Marcello-Barbiani的答案是正确的,但这不是将此函数添加到我们拥有的所有实体的好方法。
最好的方法是创建一个从DefaultContractResolver派生的新ContractResolver,并检查属性是否为Lazyloader,然后按如下所示跳过它:
public class NonLazyloaderContractResolver : DefaultContractResolver
{
public new static readonly NonLazyloaderContractResolver Instance = new NonLazyloaderContractResolver();
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
if (property.PropertyName == "LazyLoader")
{
property.ShouldSerialize = i => false;
}
return property;
}
}
在添加以上类之后,在序列化对象时将其通过JsonSerializerSettings传递:
var json = JsonConvert.SerializeObject(newProduct, new JsonSerializerSettings() {
ContractResolver = new NonLazyloaderContractResolver(),
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore });
最后,如果您使用的是asp.net core或asp.net core webapi,请将此合同作为默认的contractresolver添加到startup.cs文件中:
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddJsonOptions(options =>
{
options.SerializerSettings.ContractResolver = new NonLazyloaderContractResolver();
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
答案 2 :(得分:0)
您只能对集合进行选择,而仅检索其余数据。 这样,您的对象将根本没有导航属性。
db.YourCollection.Where(your condition)Select(x => new { id = x.id , name = x.name } );
答案 3 :(得分:0)
我知道这是旧的,但是添加
public boolean ShouldSerializeLazyLoader() { return false; }
转到要序列化的树的所有类,您将获得一个lazyloader免费JSON。
参考号:https://www.newtonsoft.com/json/help/html/ConditionalProperties.htm