【问题标题】:Limit objects in a collection from being serialized based on User根据用户限制集合中的对象被序列化
【发布时间】:2014-07-31 14:46:14
【问题描述】:

我有一个 webapi,它返回一个包含一些对象集合的对象,该集合还包含一个对象集合。这些对象中的每一个都有一个布尔值,表示该对象是否“已发布”请参阅下面的类以了解一般概念。

public class A {
  public int ID { get; set; }
  public List<B> b { get; set;}
}

public class B {
  public List<C> c { get; set; }
  public List<D> d { get; set; }
  public bool published { get; set; }
}

public class C {
  public string Title { get; set; }
  public bool published { get; set; }
}

public class D {
  public string Title { get; set; }
  public bool published { get; set; }
}

当我序列化这些对象中的任何一个时,最好的方法是什么,如果用户不满足要求,则不包含未发布的子对象,IE 不是特定角色。我可以以某种方式将数据属性添加到我的模型吗?我已经研究过使用自定义IContractResolver,但我不确定它是处理嵌套对象的最佳方式。我应该在序列化阶段处理这个问题,还是应该在从数据库中获取对象后从子项中删除未发布的对象。

【问题讨论】:

  • 我想知道是否有办法只加载与该用户角色相关的数据,这样您就不必担心在序列化时解析它。
  • 我没有完全阅读到您的文本的结尾-您有理由将所有数据从数据库中提取出来吗?据推测,唯一需要的数据是他们角色的数据 - 除非你有其他理由从数据库中删除数据,否则我会研究一个只查询所需数据的解决方案。
  • 除了序列化阶段之外,您的代码中是否还需要任何unpublished 对象?
  • 我不需要任何未发布的对象。我可以只考虑抓取已发布的对象,但使用实体框架,我想不出一个简单的方法来获取例如 AID 为 2,然后确保所有 B 都已发布,所有 C 和 D 都已发布在那些 B 中以可重用的方式发布,因此我认为我可以在这些对象的全局序列化设置中做到这一点。有什么想法吗?
  • 如果您必须这样做,您可以考虑添加一种克隆方法,该方法仅对已发布的项目进行深度克隆。虽然您可能应该弄清楚如何让您的 ORM 只获取您需要的数据。

标签: c# entity-framework json.net asp.net-web-api2


【解决方案1】:

正如 cmets(正确地)指出的那样,我的做法有点错误。

我通过两个数据库请求解决了我的问题,基本看起来像这样。

A a = null;

if(User.IsInRole("Role")){
   a = db.A.Find(Id);
} else {
   a = (from a in db.A
        join b in db.B on a.ID equals b.ID
        join c in db.C on b.ID equals c.ID
        join d in db.D on b.ID equals d.ID
        where a.ID == id && b.Published && c.Published && d.Published
        select a);
}

if(a == null)
   return NotFound();

return Ok(a);

我试图避免这样的代码,但我不确定是否有更好的方法来做到这一点。

【讨论】:

    【解决方案2】:

    实际上,我建议某些用户只加载需要的数据,因为这会提高性能。如果您想加载所有数据(已发布和未发布)的情况是微不足道的。对于只能查看已发布项目的用户,我会进行这样的查询:

    A model = context.ACollection.Where(a => a.ID == id).Select(a => 
         new A { 
             ID = a.ID, 
             b = a.b.Where(i => i.published == true).Select(i => 
                 new B{
                     published = true, 
                     c = i.c.Where(c_item => c_item.published == true),
                     d = i.d.Where(d_item => d_item.published == true)
                 })
        }).Single();
    

    这个查询应该会给你很好的性能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-11
      • 1970-01-01
      • 2010-11-30
      • 2020-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多