避免 lazyloader 属性
Avoid lazyloader attribute
我一直在寻找如何避免 return 没有属性 lazyLoader 的列表,我想继续使用 lazyLoader 但我不想 return 当我 return 来自我的控制器的我的实体的整个列表时的属性
我正在使用 .NET 核心。
[
{
"lazyLoader": {},
"id": "id1"
"name": "name"
},
{
"lazyLoader": {},
"id": "id2",
"name": "name2"
}
]
您可以进行 select 收集,仅检索其余数据。
这样您的对象将根本没有导航 属性。
db.YourCollection.Where(your condition)Select(x => new { id = x.id , name = x.name } );
在 Entity Framework 中,如果您有一个对象,其中一个或多个属性使用延迟加载,请使用 GetType().Name 检查其运行时类型名称。例如,对于 Car class 的对象,您会注意到运行时类型实际上是一种叫做 CarProxy 的东西,它是Entity Framework 使用 反射 创建的临时内存类型。此 "fake" 代理 class 的基本类型是 Car,具有所有原始 Car 属性,但包括一个额外的一个叫做 LazyLoader 用于可能需要它的属性。
如果您进一步检查此 "fake" CarProxy 类型,您还会看到 Assembly.IsDynamic = true,这表明 class 是使用反射动态创建的(参见 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" 属性 可能会再次出现。我还没有测试过,所以我不能肯定。
我知道这是旧的,但是添加
public boolean ShouldSerializeLazyLoader() { return false; }
到所有 类 你想要序列化的树下,你将免费获得一个 lazyloader JSON。
参考:https://www.newtonsoft.com/json/help/html/ConditionalProperties.htm
这个问题的检查答案只适用于根对象,如果我们有很多嵌套的延迟加载对象,这个解决方案将不起作用。
虽然 @ 的答案是正确的,但将此功能添加到我们拥有的所有实体并不是一个好方法。
最好的方法是创建一个从 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;
}
}
在上面添加之后 class 在序列化对象时通过 JsonSerializerSettings 传递它:
var json = JsonConvert.SerializeObject(newProduct, new JsonSerializerSettings() {
ContractResolver = new NonLazyloaderContractResolver(),
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore });
最后,如果您使用的是 asp.net 核心或 asp.net 核心 webapi,请在 startup.cs 文件中添加此合约作为默认合约解析器:
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddJsonOptions(options =>
{
options.SerializerSettings.ContractResolver = new NonLazyloaderContractResolver();
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
我一直在寻找如何避免 return 没有属性 lazyLoader 的列表,我想继续使用 lazyLoader 但我不想 return 当我 return 来自我的控制器的我的实体的整个列表时的属性
我正在使用 .NET 核心。
[
{
"lazyLoader": {},
"id": "id1"
"name": "name"
},
{
"lazyLoader": {},
"id": "id2",
"name": "name2"
}
]
您可以进行 select 收集,仅检索其余数据。 这样您的对象将根本没有导航 属性。
db.YourCollection.Where(your condition)Select(x => new { id = x.id , name = x.name } );
在 Entity Framework 中,如果您有一个对象,其中一个或多个属性使用延迟加载,请使用 GetType().Name 检查其运行时类型名称。例如,对于 Car class 的对象,您会注意到运行时类型实际上是一种叫做 CarProxy 的东西,它是Entity Framework 使用 反射 创建的临时内存类型。此 "fake" 代理 class 的基本类型是 Car,具有所有原始 Car 属性,但包括一个额外的一个叫做 LazyLoader 用于可能需要它的属性。
如果您进一步检查此 "fake" CarProxy 类型,您还会看到 Assembly.IsDynamic = true,这表明 class 是使用反射动态创建的(参见 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" 属性 可能会再次出现。我还没有测试过,所以我不能肯定。
我知道这是旧的,但是添加
public boolean ShouldSerializeLazyLoader() { return false; }
到所有 类 你想要序列化的树下,你将免费获得一个 lazyloader JSON。
参考:https://www.newtonsoft.com/json/help/html/ConditionalProperties.htm
这个问题的检查答案只适用于根对象,如果我们有很多嵌套的延迟加载对象,这个解决方案将不起作用。
虽然 @
最好的方法是创建一个从 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;
}
}
在上面添加之后 class 在序列化对象时通过 JsonSerializerSettings 传递它:
var json = JsonConvert.SerializeObject(newProduct, new JsonSerializerSettings() {
ContractResolver = new NonLazyloaderContractResolver(),
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore });
最后,如果您使用的是 asp.net 核心或 asp.net 核心 webapi,请在 startup.cs 文件中添加此合约作为默认合约解析器:
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddJsonOptions(options =>
{
options.SerializerSettings.ContractResolver = new NonLazyloaderContractResolver();
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});