Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Updating a List record within a record with c# and Linq, looking for something cleaner than add and remove

Updating a List record within a record with c# and Linq, looking for something cleaner than add and remove

Scheduled Pinned Locked Moved C#
csharptutorialasp-netmongodbdotnet
7 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    jkirkerx
    wrote on last edited by
    #1

    So this is really a MongoDb document class for a category, that has subCategories. Below is an example of how the data is structured. For some reason, I'm drawing a blank on how to do this, or I've never really had a need to do it. I want to update 1 sub category using Linq, so I can just write the whole category document using MongoDb as a ReplaceOneAsync(). But I just can't figure out how. This is in a .Net Core Controller.

    {
    "_id" : "5d9f97eb29d7b329209b13cb",
    "Name" : "Solid State Drives",
    "Description": "Great Drive",
    "SubCategories" : [
    {
    "_id" : "5da8a1d7afb5d4084c80c9a4",
    "Name" : "NVMe",
    "Description" : "Fast Drive"
    },
    {
    "_id" : "5da8a1d7afb5d4084c80c9a4",
    "Name" : "2.5\" Form Factor",
    "Description" : "Small Drive"
    }
    }

    I'm thinking this, but VS didn't like the left side.

    var cR = GetCategory(cid);
    cR.SubCategories.FirstOrDefault(sc => sc.Id == subCategory.Id) = subCategory;
    UpdateCategory(cid, cR);

    I know I can do this, but I would like to preserve the original order.

    cR.SubCategories.Remove(subCategory);
    cR.SubCategories.Add(subCategory);

    Or this

    var idx = -1;
    foreach (var sc in cR.SubCategories)
    {
    idx++;
    if (sc.Id.Equals(subCategory.Id))
    {
    cR.SubCategories[idx] = subCategory;
    }
    }

    I'm just looking for clean 1 liner to do this with if it exist.

    If it ain't broke don't fix it Discover my world at jkirkerx.com

    L Richard DeemingR J 4 Replies Last reply
    0
    • J jkirkerx

      So this is really a MongoDb document class for a category, that has subCategories. Below is an example of how the data is structured. For some reason, I'm drawing a blank on how to do this, or I've never really had a need to do it. I want to update 1 sub category using Linq, so I can just write the whole category document using MongoDb as a ReplaceOneAsync(). But I just can't figure out how. This is in a .Net Core Controller.

      {
      "_id" : "5d9f97eb29d7b329209b13cb",
      "Name" : "Solid State Drives",
      "Description": "Great Drive",
      "SubCategories" : [
      {
      "_id" : "5da8a1d7afb5d4084c80c9a4",
      "Name" : "NVMe",
      "Description" : "Fast Drive"
      },
      {
      "_id" : "5da8a1d7afb5d4084c80c9a4",
      "Name" : "2.5\" Form Factor",
      "Description" : "Small Drive"
      }
      }

      I'm thinking this, but VS didn't like the left side.

      var cR = GetCategory(cid);
      cR.SubCategories.FirstOrDefault(sc => sc.Id == subCategory.Id) = subCategory;
      UpdateCategory(cid, cR);

      I know I can do this, but I would like to preserve the original order.

      cR.SubCategories.Remove(subCategory);
      cR.SubCategories.Add(subCategory);

      Or this

      var idx = -1;
      foreach (var sc in cR.SubCategories)
      {
      idx++;
      if (sc.Id.Equals(subCategory.Id))
      {
      cR.SubCategories[idx] = subCategory;
      }
      }

      I'm just looking for clean 1 liner to do this with if it exist.

      If it ain't broke don't fix it Discover my world at jkirkerx.com

      L Offline
      L Offline
      Luc Pattyn
      wrote on last edited by
      #2

      You can do

      public class Jef {
      	public int a;
      	public int b;
      }
      public class Test {
      	List list = new List();
      
      	private void test1() {
      		list.First().b = 13;
      		list.First(j => j.a == 12).b = 14;
      	}
      }
      

      when Jef is a class, as list.First() then returns the reference of a Jef object. And when null, it would throw a NullRefExc. You can't when Jef is a struct, as structs are value types, there is no reference or pointer to a value type. With structs the compiler rightfully gives the error: cannot modify the return value of ... because it is not a variable. Furthermore, I'm wondering what you expect from FirstOrDefault as a target for assignment: when no items match, the default would be what? where would the new value have to go? :)

      Luc Pattyn [My Articles] Nil Volentibus Arduum

      J 1 Reply Last reply
      0
      • J jkirkerx

        So this is really a MongoDb document class for a category, that has subCategories. Below is an example of how the data is structured. For some reason, I'm drawing a blank on how to do this, or I've never really had a need to do it. I want to update 1 sub category using Linq, so I can just write the whole category document using MongoDb as a ReplaceOneAsync(). But I just can't figure out how. This is in a .Net Core Controller.

        {
        "_id" : "5d9f97eb29d7b329209b13cb",
        "Name" : "Solid State Drives",
        "Description": "Great Drive",
        "SubCategories" : [
        {
        "_id" : "5da8a1d7afb5d4084c80c9a4",
        "Name" : "NVMe",
        "Description" : "Fast Drive"
        },
        {
        "_id" : "5da8a1d7afb5d4084c80c9a4",
        "Name" : "2.5\" Form Factor",
        "Description" : "Small Drive"
        }
        }

        I'm thinking this, but VS didn't like the left side.

        var cR = GetCategory(cid);
        cR.SubCategories.FirstOrDefault(sc => sc.Id == subCategory.Id) = subCategory;
        UpdateCategory(cid, cR);

        I know I can do this, but I would like to preserve the original order.

        cR.SubCategories.Remove(subCategory);
        cR.SubCategories.Add(subCategory);

        Or this

        var idx = -1;
        foreach (var sc in cR.SubCategories)
        {
        idx++;
        if (sc.Id.Equals(subCategory.Id))
        {
        cR.SubCategories[idx] = subCategory;
        }
        }

        I'm just looking for clean 1 liner to do this with if it exist.

        If it ain't broke don't fix it Discover my world at jkirkerx.com

        Richard DeemingR Offline
        Richard DeemingR Offline
        Richard Deeming
        wrote on last edited by
        #3

        How about:

        int index = cR.SubCategories.IndexOf(subCategory);
        if (index == -1)
        {
        cR.SubCategories.Add(subCategory);
        }
        else
        {
        cR.SubCategories.RemoveAt(index);
        cR.SubCategories.Insert(index, subCategory);
        }

        Or:

        int index = cR.SubCategories.IndexOf(subCategory);
        if (index == -1)
        {
        cR.SubCategories.Add(subCategory);
        }
        else
        {
        cR.SubCategories[index] = subCategory;
        }

        Unfortunately, to assign to the value returned from a method, you'd need a ref return[^]. And you can't do that with a List<T>, so you'd have to implement your own list class.


        "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

        "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

        1 Reply Last reply
        0
        • J jkirkerx

          So this is really a MongoDb document class for a category, that has subCategories. Below is an example of how the data is structured. For some reason, I'm drawing a blank on how to do this, or I've never really had a need to do it. I want to update 1 sub category using Linq, so I can just write the whole category document using MongoDb as a ReplaceOneAsync(). But I just can't figure out how. This is in a .Net Core Controller.

          {
          "_id" : "5d9f97eb29d7b329209b13cb",
          "Name" : "Solid State Drives",
          "Description": "Great Drive",
          "SubCategories" : [
          {
          "_id" : "5da8a1d7afb5d4084c80c9a4",
          "Name" : "NVMe",
          "Description" : "Fast Drive"
          },
          {
          "_id" : "5da8a1d7afb5d4084c80c9a4",
          "Name" : "2.5\" Form Factor",
          "Description" : "Small Drive"
          }
          }

          I'm thinking this, but VS didn't like the left side.

          var cR = GetCategory(cid);
          cR.SubCategories.FirstOrDefault(sc => sc.Id == subCategory.Id) = subCategory;
          UpdateCategory(cid, cR);

          I know I can do this, but I would like to preserve the original order.

          cR.SubCategories.Remove(subCategory);
          cR.SubCategories.Add(subCategory);

          Or this

          var idx = -1;
          foreach (var sc in cR.SubCategories)
          {
          idx++;
          if (sc.Id.Equals(subCategory.Id))
          {
          cR.SubCategories[idx] = subCategory;
          }
          }

          I'm just looking for clean 1 liner to do this with if it exist.

          If it ain't broke don't fix it Discover my world at jkirkerx.com

          Richard DeemingR Offline
          Richard DeemingR Offline
          Richard Deeming
          wrote on last edited by
          #4

          Just for fun, here's a simplistic - and not thoroughly tested! - example using ref returns:

          public readonly struct SubCategory : IEquatable<SubCategory>
          {
          public SubCategory(int id, string name) => (Id, Name) = (id, name);
          public int Id { get; }
          public string Name { get; }
          public override int GetHashCode() => Id;
          public override bool Equals(object obj) => obj is SubCategory other && Equals(other);
          public bool Equals(SubCategory other) => Id == other.Id;
          }

          public class SubCategoryList : IEnumerable<SubCategory>
          {
          private SubCategory[] _categories = new SubCategory[4];
          private int _length;

          public int Count => \_length;
          public int Capacity => \_categories.Length;
          public ref SubCategory this\[int index\] => ref \_categories\[index\];
          
          public ref SubCategory FindOrAdd(int id)
          {
              for (int index = 0; index < \_length; index++)
              {
                  if (\_categories\[index\].Id == id)
                  {
                      return ref \_categories\[index\];
                  }
              }
              
              Add(new SubCategory(id, null));
              return ref \_categories\[\_length - 1\];
          }
          
          public void Add(SubCategory value)
          {
              if (\_length == \_categories.Length)
              {
                  int newSize = \_length \* 2;
                  Array.Resize(ref \_categories, newSize);
              }
              
              \_categories\[\_length\] = value;
              \_length++;
          }
          
          public IEnumerator<SubCategory> GetEnumerator()
          {
              SubCategory\[\] categories = \_categories;
              int length = \_length;
              
              for (int index = 0; index < length; index++)
              {
                  yield return categories\[index\];
              }
          }
          
          IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
          

          }

          public class Category
          {
          public SubCategoryList SubCategories { get; } = new SubCategoryList();
          }

          Usage:

          var cR = new Category
          {
          SubCategories =
          {
          new SubCategory(1, "C1"),
          new SubCategory(2, "C2"),
          new SubCategory(3, "C3"),
          }
          };

          cR.SubCategories.FindOrAdd(2) = new SubCategory(2, "X2");
          cR.SubCategories.FindOrAdd(42) = new SubCategory(42, "Z42");

          NB: I wouldn't recommend using this approach. :)


          "These people looked deep within my soul and assigned me a number based on the

          "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

          J 1 Reply Last reply
          0
          • L Luc Pattyn

            You can do

            public class Jef {
            	public int a;
            	public int b;
            }
            public class Test {
            	List list = new List();
            
            	private void test1() {
            		list.First().b = 13;
            		list.First(j => j.a == 12).b = 14;
            	}
            }
            

            when Jef is a class, as list.First() then returns the reference of a Jef object. And when null, it would throw a NullRefExc. You can't when Jef is a struct, as structs are value types, there is no reference or pointer to a value type. With structs the compiler rightfully gives the error: cannot modify the return value of ... because it is not a variable. Furthermore, I'm wondering what you expect from FirstOrDefault as a target for assignment: when no items match, the default would be what? where would the new value have to go? :)

            Luc Pattyn [My Articles] Nil Volentibus Arduum

            J Offline
            J Offline
            jkirkerx
            wrote on last edited by
            #5

            On the FirstOrDefault, I know it's there because it's an update API. But now that you have my wheels turning, if multi-user and the sub category is deleted, then it fails. Category is a class.

            If it ain't broke don't fix it Discover my world at jkirkerx.com

            1 Reply Last reply
            0
            • Richard DeemingR Richard Deeming

              Just for fun, here's a simplistic - and not thoroughly tested! - example using ref returns:

              public readonly struct SubCategory : IEquatable<SubCategory>
              {
              public SubCategory(int id, string name) => (Id, Name) = (id, name);
              public int Id { get; }
              public string Name { get; }
              public override int GetHashCode() => Id;
              public override bool Equals(object obj) => obj is SubCategory other && Equals(other);
              public bool Equals(SubCategory other) => Id == other.Id;
              }

              public class SubCategoryList : IEnumerable<SubCategory>
              {
              private SubCategory[] _categories = new SubCategory[4];
              private int _length;

              public int Count => \_length;
              public int Capacity => \_categories.Length;
              public ref SubCategory this\[int index\] => ref \_categories\[index\];
              
              public ref SubCategory FindOrAdd(int id)
              {
                  for (int index = 0; index < \_length; index++)
                  {
                      if (\_categories\[index\].Id == id)
                      {
                          return ref \_categories\[index\];
                      }
                  }
                  
                  Add(new SubCategory(id, null));
                  return ref \_categories\[\_length - 1\];
              }
              
              public void Add(SubCategory value)
              {
                  if (\_length == \_categories.Length)
                  {
                      int newSize = \_length \* 2;
                      Array.Resize(ref \_categories, newSize);
                  }
                  
                  \_categories\[\_length\] = value;
                  \_length++;
              }
              
              public IEnumerator<SubCategory> GetEnumerator()
              {
                  SubCategory\[\] categories = \_categories;
                  int length = \_length;
                  
                  for (int index = 0; index < length; index++)
                  {
                      yield return categories\[index\];
                  }
              }
              
              IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
              

              }

              public class Category
              {
              public SubCategoryList SubCategories { get; } = new SubCategoryList();
              }

              Usage:

              var cR = new Category
              {
              SubCategories =
              {
              new SubCategory(1, "C1"),
              new SubCategory(2, "C2"),
              new SubCategory(3, "C3"),
              }
              };

              cR.SubCategories.FindOrAdd(2) = new SubCategory(2, "X2");
              cR.SubCategories.FindOrAdd(42) = new SubCategory(42, "Z42");

              NB: I wouldn't recommend using this approach. :)


              "These people looked deep within my soul and assigned me a number based on the

              J Offline
              J Offline
              jkirkerx
              wrote on last edited by
              #6

              Wow, that was an explosion of thought! I knew I could edit my class to help out, but it's been awhile since I've done it. This expands on Luc's thought in using struct and class. I've never used struct or have heard of it. But me going NoSQL, I can see where this is going to be a requirement for me to learn, now that I'm building a store and getting more complex with using data. I need time to adsorb this new info. Thanks Richard and Luc!

              If it ain't broke don't fix it Discover my world at jkirkerx.com

              1 Reply Last reply
              0
              • J jkirkerx

                So this is really a MongoDb document class for a category, that has subCategories. Below is an example of how the data is structured. For some reason, I'm drawing a blank on how to do this, or I've never really had a need to do it. I want to update 1 sub category using Linq, so I can just write the whole category document using MongoDb as a ReplaceOneAsync(). But I just can't figure out how. This is in a .Net Core Controller.

                {
                "_id" : "5d9f97eb29d7b329209b13cb",
                "Name" : "Solid State Drives",
                "Description": "Great Drive",
                "SubCategories" : [
                {
                "_id" : "5da8a1d7afb5d4084c80c9a4",
                "Name" : "NVMe",
                "Description" : "Fast Drive"
                },
                {
                "_id" : "5da8a1d7afb5d4084c80c9a4",
                "Name" : "2.5\" Form Factor",
                "Description" : "Small Drive"
                }
                }

                I'm thinking this, but VS didn't like the left side.

                var cR = GetCategory(cid);
                cR.SubCategories.FirstOrDefault(sc => sc.Id == subCategory.Id) = subCategory;
                UpdateCategory(cid, cR);

                I know I can do this, but I would like to preserve the original order.

                cR.SubCategories.Remove(subCategory);
                cR.SubCategories.Add(subCategory);

                Or this

                var idx = -1;
                foreach (var sc in cR.SubCategories)
                {
                idx++;
                if (sc.Id.Equals(subCategory.Id))
                {
                cR.SubCategories[idx] = subCategory;
                }
                }

                I'm just looking for clean 1 liner to do this with if it exist.

                If it ain't broke don't fix it Discover my world at jkirkerx.com

                J Offline
                J Offline
                jkirkerx
                wrote on last edited by
                #7

                So I was having trouble with my Angular Category program in which I would update a categories subCategory and it would add a subCategory or update the wrong one with remove and add, and IndexOf. So I pickup a Category Model in the API via HTTPGet and send it to Angular. Then I send just the SubCategory model within Category back to a different API via HTTPPut. In this API, I pick up the Category from MongoDB, then do var index = category.SubCategories.IndexOf(subCategory); and index returns -1. So I did a First to get the index

                var index = category.SubCategories.IndexOf(category.SubCategories.First(sc => sc.Id == subCategory.Id));

                and I get 2 back which is correct. So in my other modules, I can pass a model to Angular, work on it and pass it back no problem. I suspect if I would of passed back the Category in whole the IndexOf(subCategory) would of worked. I'm just curious about this. Perhaps an explanation or knowledge will help create better designs.

                If it ain't broke don't fix it Discover my world at jkirkerx.com

                1 Reply Last reply
                0
                Reply
                • Reply as topic
                Log in to reply
                • Oldest to Newest
                • Newest to Oldest
                • Most Votes


                • Login

                • Don't have an account? Register

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • World
                • Users
                • Groups