转载

MongoDB学习笔记~大叔框架实体更新支持N层嵌套~递归递归我爱你!

回到目录

递归递归我爱你!保要你想做,就一定能成功!

从一到二,从二到三,它是容易的,也是没什么搞高的,或者说,它是一种流水线的方式,而从三到十,它注定要有一个质的突破,否则,它会把你累死,代码写的让你自己都觉得想吐!有时,我们是被逼出来的,对于一种功能的实现,我们有时需要有从三到十的态度……

回归回实例,在mongodb中实体可以嵌套,这在C#里叫做复杂属性,即类中也有类级的属性,这在面向对象里叫做“组合”,它经常在日常开发环境中见到,大家都耳熟能详了,呵呵,而在mongodb里,如果希望对N层嵌套的类型进行update操作,这绝对不是一件容易的事,最起码在大叔框架里,在面向linq的语法里,它并不容易,但经过大叔的努力,和对递归的依赖,把这个问题解决了!

这才有今天的文章:递归递归我爱你!

一 从超级变态的类开始

public class Person : Base {  public Person()  {   Contact = new Test.Contact();   OrderList = new List<Order>();  }  public string Name { get; set; }  public DateTime LastContact { get; set; }  public DateTime Birthday { get; set; }  public int Age { get; set; }  #region 值对象  /// <summary>  /// 统计  /// </summary>  public Total Total { get; set; }  /// <summary>  /// 联系方式和地址  /// </summary>  public Contact Contact { get; set; }  #endregion  #region 列表实体  public List<Order> OrderList { get; set; }  #endregion } public class Section {  public string SectionID { get; set; }  public string SectionName { get; set; } } public class Area {  public Area()  {   Section = new Section();  }  public string Province { get; set; }  public string City { get; set; }  public string District { get; set; }  public Section Section { get; set; } } public class Contact {  public Contact()  {   Area = new Area();  }  public string PostCode { get; set; }  public string Email { get; set; }  public string Phone { get; set; }  public Area Area { get; set; } } public class Total {  public int Count { get; set; }  public int Max { get; set; } } public class Order {  public Order()  {   Id = MongoDB.Bson.ObjectId.GenerateNewId().ToString();   this.OrderDetail = new List<OrderDetail>();   this.User_Info = new User_Info();  }  public string UserId { get; set; }  public string UserName { get; set; }  public string Id { get; set; }  public double Price { get; set; }  public DateTime AddTime { get; set; }  public User_Info User_Info { get; set; }  public List<OrderDetail> OrderDetail { get; set; } } public class User_Info {  public User_Info()  {   Id = MongoDB.Bson.ObjectId.GenerateNewId().ToString();  }  public string Id { get; set; }  public string Name { get; set; } } public class OrderDetail {  public OrderDetail()  {   Id = MongoDB.Bson.ObjectId.GenerateNewId().ToString();  }  public string Id { get; set; }  public string OrderId { get; set; }  public string ProductName { get; set; }  public int Count { get; set; }  public double Price { get; set; }  public string SellerId { get; set; } } 

看到上面的类,绝对够你喝一壶的,呵呵,这是一个复杂的类型People,它有实体属性contact和列表属性OrderList

而对于之前大叔的框架里,这种结构是不被支持的,大叔只能支持到3级嵌套,但这显然是不够的,最后大叔硬着头皮冲了上来,把这个骨头啃掉了,哈哈!

下面贡献我的Recursion代码

/// <summary>   /// 递归构建Update操作串   /// </summary>   /// <param name="fieldList"></param>   /// <param name="property"></param>   /// <param name="propertyValue"></param>   /// <param name="item"></param>   /// <param name="father"></param>   private void GenerateRecursion(      List<UpdateDefinition<TEntity>> fieldList,      PropertyInfo property,      object propertyValue,      TEntity item,      string father)   {    //复杂类型    if (property.PropertyType.IsClass && property.PropertyType != typeof(string) && propertyValue != null)    {     //集合     if (typeof(IList).IsAssignableFrom(propertyValue.GetType()))     {      foreach (var sub in property.PropertyType.GetProperties(BindingFlags.Instance | BindingFlags.Public))      {       if (sub.PropertyType.IsClass && sub.PropertyType != typeof(string))       {        var arr = propertyValue as IList;        if (arr != null && arr.Count > 0)        {         for (int index = 0; index < arr.Count; index++)         {          foreach (var subInner in sub.PropertyType.GetProperties(BindingFlags.Instance | BindingFlags.Public))          {           if (string.IsNullOrWhiteSpace(father))            GenerateRecursion(fieldList, subInner, subInner.GetValue(arr[index]), item, property.Name + "." + index);           else            GenerateRecursion(fieldList, subInner, subInner.GetValue(arr[index]), item, father + "." + property.Name + "." + index);          }         }        }       }      }     }     //实体     else     {      foreach (var sub in property.PropertyType.GetProperties(BindingFlags.Instance | BindingFlags.Public))      {       if (string.IsNullOrWhiteSpace(father))        GenerateRecursion(fieldList, sub, sub.GetValue(propertyValue), item, property.Name);       else        GenerateRecursion(fieldList, sub, sub.GetValue(propertyValue), item, father + "." + property.Name);      }     }    }    //简单类型    else    {     if (property.Name != EntityKey)//更新集中不能有实体键_id     {      if (string.IsNullOrWhiteSpace(father))       fieldList.Add(Builders<TEntity>.Update.Set(property.Name, propertyValue));      else       fieldList.Add(Builders<TEntity>.Update.Set(father + "." + property.Name, propertyValue));     }    }   }   /// <summary>   /// 构建Mongo的更新表达式   /// </summary>   /// <param name="entity"></param>   /// <returns></returns>   private List<UpdateDefinition<TEntity>> GeneratorMongoUpdate(TEntity item)   {    var fieldList = new List<UpdateDefinition<TEntity>>();    foreach (var property in typeof(TEntity).GetProperties(BindingFlags.Instance | BindingFlags.Public))    {     GenerateRecursion(fieldList, property, property.GetValue(item), item, string.Empty);    }    return fieldList;   } 

最后的结果,当然是在N层失败之后,取得了成功,呵呵!

最后,送给大家一句,多看看数据结构和算法,对各位在程序开发领域,一定有非常大的帮助,最起码在看问题的角度上,会有更多的,更合理的选择!

回到目录

正文到此结束
Loading...