2

我一直在寻找如何避免返回没有属性lazyLoader的列表,我想继续使用lazyLoader,但是当我从控制器返回整个实体列表时,我不想返回属性

我正在使用 .NET 核心。

[
  {
    "lazyLoader": {},
    "id": "id1"
    "name": "name"
  },
  {
    "lazyLoader": {},
    "id": "id2",
    "name": "name2"
  }
]
4

4 回答 4

1

您可以选择仅检索其余数据的集合。这样,您的对象将根本没有 Navigation 属性。

db.YourCollection.Where(your condition)Select(x => new { id = x.id , name = x.name } );
于 2018-09-05T15:07:17.270 回答
1

在 Entity Framework 中,如果您的对象的一个​​或多个属性使用延迟加载,请使用 GetType().Name 检查其运行时类型名称。例如,对于Car类的对象,您会注意到运行时类型实际上是称为CarProxy的东西,它是 Entity Framework 使用反射创建的临时内存类型。这个“假”代理类的基类型是Car,并且具有所有原始Car属性,但包括一个称为LazyLoader的额外属性,用于可能需要它的属性。

如果您进一步检查这种“假” CarProxy类型,您还将看到Assembly.IsDynamic = true,这表明该类是使用反射动态创建的(请参阅文档):

var TheCar = DBContext.Cars.Find(1);
Console.WriteLine(TheCar.GetType().Assembly.IsDynamic.ToString()); //will echo "true"

幸运的是,Newtonsoft.JsonJsonConvert.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”属性可能会再次出现。我没有测试过,所以我不能肯定。

于 2019-05-03T16:16:10.510 回答
1

我知道这是旧的,但添加

public boolean ShouldSerializeLazyLoader() { return false; }

到你想要序列化的那些树下的所有类,你将得到一个惰性加载器免费的 JSON。

参考:https ://www.newtonsoft.com/json/help/html/ConditionalProperties.htm

于 2019-05-30T19:05:46.847 回答
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,请将此合同添加为 startup.cs 文件中的默认contractresolver:

services.AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
        .AddJsonOptions(options =>
        {
            options.SerializerSettings.ContractResolver = new NonLazyloaderContractResolver();
            options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        });
于 2019-06-14T05:40:36.257 回答