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. Dynamically Insert A Property Into A LINQ Query Statement

Dynamically Insert A Property Into A LINQ Query Statement

Scheduled Pinned Locked Moved C#
linqcsharpdatabasefunctionalhelp
9 Posts 5 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.
  • M Offline
    M Offline
    MadDashCoder
    wrote on last edited by
    #1

    Suppose I have 2 objects like the following

    public class Toy
    {
    public int ID{get;set;}
    public double Price{get;set;}
    public sting Color{get; set;}
    }
    public class Merchandise
    {
    public List toyList;
    public Merchandise()
    {
    toyList= new List();
    toyList.Add(new Toy {ID = 1, Price = 10, Color = "Red"});
    toyList.Add(new Toy {ID = 2, Price = 10, Color = "White"});
    toyList.Add(new Toy {ID = 3, Price = 10, Color = "Black"});
    }

    public string this[int toyId, string toyProperty]
    {
    get{return listOfProducts.FirstOrDefault(prod => prod.Id == productId);}
    set{listOfProducts.FirstOrDefault(prod => prod.Id == productId).toyProperty = value;}
    }
    }

    I want to be able to dynamically choose which property to insert into my LINQ query inside of the Indexer's set property. That way I can set the Price or Color of the Toy object dynamically. I created the toyProperty parameter in the Indexer parameter list so that the code that will consume the Indexer will be able to pass a value to the toyProperty in the LINQ Query. The code consuming the Indexer will look something like the following

    public double price = txtPrice.Text;
    public string color = txtColor.Text;

    public Merchandise item = new Merchandise();
    //Change Price Dynamically
    item[2, "Price"].Price = price;

    //Change Color Dynamically
    item[2, "Color"].Color = color;

    My Lambda Expression inside the set property of the Indexer does not work of course but I wonder if it is missing something that could help to make it work.

    S D M L 4 Replies Last reply
    0
    • M MadDashCoder

      Suppose I have 2 objects like the following

      public class Toy
      {
      public int ID{get;set;}
      public double Price{get;set;}
      public sting Color{get; set;}
      }
      public class Merchandise
      {
      public List toyList;
      public Merchandise()
      {
      toyList= new List();
      toyList.Add(new Toy {ID = 1, Price = 10, Color = "Red"});
      toyList.Add(new Toy {ID = 2, Price = 10, Color = "White"});
      toyList.Add(new Toy {ID = 3, Price = 10, Color = "Black"});
      }

      public string this[int toyId, string toyProperty]
      {
      get{return listOfProducts.FirstOrDefault(prod => prod.Id == productId);}
      set{listOfProducts.FirstOrDefault(prod => prod.Id == productId).toyProperty = value;}
      }
      }

      I want to be able to dynamically choose which property to insert into my LINQ query inside of the Indexer's set property. That way I can set the Price or Color of the Toy object dynamically. I created the toyProperty parameter in the Indexer parameter list so that the code that will consume the Indexer will be able to pass a value to the toyProperty in the LINQ Query. The code consuming the Indexer will look something like the following

      public double price = txtPrice.Text;
      public string color = txtColor.Text;

      public Merchandise item = new Merchandise();
      //Change Price Dynamically
      item[2, "Price"].Price = price;

      //Change Color Dynamically
      item[2, "Color"].Color = color;

      My Lambda Expression inside the set property of the Indexer does not work of course but I wonder if it is missing something that could help to make it work.

      S Offline
      S Offline
      Sascha Lefevre
      wrote on last edited by
      #2

      While there would be a way to do something close to what you want (which I wouldn't recommend), I don't think you've thought this through: The indexer-getter "attempts" to return a Toy but you declared the type of the indexer as string. Maybe you intended to dynamically access the given toyProperty there as well and return it formatted as a string? Your usage-example actually employs the getter, not the setter, because you (statically) access a property before the assignment. Apart from that, you're planning on conceding syntax correctness and type safety here. Why? If you tell us your ultimate goal here - why you think you need this - we will probably be able to provide you with ideas for better solutions.

      If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson

      M 1 Reply Last reply
      0
      • S Sascha Lefevre

        While there would be a way to do something close to what you want (which I wouldn't recommend), I don't think you've thought this through: The indexer-getter "attempts" to return a Toy but you declared the type of the indexer as string. Maybe you intended to dynamically access the given toyProperty there as well and return it formatted as a string? Your usage-example actually employs the getter, not the setter, because you (statically) access a property before the assignment. Apart from that, you're planning on conceding syntax correctness and type safety here. Why? If you tell us your ultimate goal here - why you think you need this - we will probably be able to provide you with ideas for better solutions.

        If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson

        M Offline
        M Offline
        MadDashCoder
        wrote on last edited by
        #3

        Thanks for your reply. In my test project my code does return a Toy object. It looks something like this

        public Toy this[int toyId, string toyProperty]
        {
        get{return listOfProducts.FirstOrDefault(prod => prod.Id == productId);}
        set{listOfProducts.FirstOrDefault(prod => prod.Id == productId).toyProperty = value;}
        }

        This is just a test project to find out how I can use a single set property to change different properties using one LINQ Query. Also you are correct my syntax should have been

        //Change Price Dynamically
        item[2, "Price"] = price;

        //Change Color Dynamically
        item[2, "Color"] = color;

        S 1 Reply Last reply
        0
        • M MadDashCoder

          Thanks for your reply. In my test project my code does return a Toy object. It looks something like this

          public Toy this[int toyId, string toyProperty]
          {
          get{return listOfProducts.FirstOrDefault(prod => prod.Id == productId);}
          set{listOfProducts.FirstOrDefault(prod => prod.Id == productId).toyProperty = value;}
          }

          This is just a test project to find out how I can use a single set property to change different properties using one LINQ Query. Also you are correct my syntax should have been

          //Change Price Dynamically
          item[2, "Price"] = price;

          //Change Color Dynamically
          item[2, "Color"] = color;

          S Offline
          S Offline
          Sascha Lefevre
          wrote on last edited by
          #4

          MadDashCoder wrote:

          In my test project my code does return a Toy object.

          Then the value in the setter would also be of type Toy. The only half sensible types to use would be object or string.

          MadDashCoder wrote:

          This is just a test project to find out how I can use a single set property to change different properties using one LINQ Query.

          It's always going to be messy and I would avoid it unless there's some very compelling reason to do so. Staying with your pseudo-code-style, it should look like this:

          public object this[int toyId, string toyProperty]
          {
          get { return listOfProducts.Single(prod => prod.Id == toyId).toyProperty; }
          set { listOfProducts.Single(prod => prod.Id == toyId).toyProperty = value; }
          }

          And to resolve the .toyProperty pseudo-code you would have to use reflection or reflection+expressions.

          If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson

          1 Reply Last reply
          0
          • M MadDashCoder

            Suppose I have 2 objects like the following

            public class Toy
            {
            public int ID{get;set;}
            public double Price{get;set;}
            public sting Color{get; set;}
            }
            public class Merchandise
            {
            public List toyList;
            public Merchandise()
            {
            toyList= new List();
            toyList.Add(new Toy {ID = 1, Price = 10, Color = "Red"});
            toyList.Add(new Toy {ID = 2, Price = 10, Color = "White"});
            toyList.Add(new Toy {ID = 3, Price = 10, Color = "Black"});
            }

            public string this[int toyId, string toyProperty]
            {
            get{return listOfProducts.FirstOrDefault(prod => prod.Id == productId);}
            set{listOfProducts.FirstOrDefault(prod => prod.Id == productId).toyProperty = value;}
            }
            }

            I want to be able to dynamically choose which property to insert into my LINQ query inside of the Indexer's set property. That way I can set the Price or Color of the Toy object dynamically. I created the toyProperty parameter in the Indexer parameter list so that the code that will consume the Indexer will be able to pass a value to the toyProperty in the LINQ Query. The code consuming the Indexer will look something like the following

            public double price = txtPrice.Text;
            public string color = txtColor.Text;

            public Merchandise item = new Merchandise();
            //Change Price Dynamically
            item[2, "Price"].Price = price;

            //Change Color Dynamically
            item[2, "Color"].Color = color;

            My Lambda Expression inside the set property of the Indexer does not work of course but I wonder if it is missing something that could help to make it work.

            D Offline
            D Offline
            Dave Kreskowiak
            wrote on last edited by
            #5

            After thinking about this for a couple of minutes, the answer is "probably yes", but the code ends up being hideously complex because of other property types outside of the string case you're showing. You have to handle all possible types through reflection, even structures and class instances. This isn't something I've done, nor want to because of time.

            A guide to posting questions on CodeProject

            Click this: Asking questions is a skill. Seriously, do it.
            Dave Kreskowiak

            1 Reply Last reply
            0
            • M MadDashCoder

              Suppose I have 2 objects like the following

              public class Toy
              {
              public int ID{get;set;}
              public double Price{get;set;}
              public sting Color{get; set;}
              }
              public class Merchandise
              {
              public List toyList;
              public Merchandise()
              {
              toyList= new List();
              toyList.Add(new Toy {ID = 1, Price = 10, Color = "Red"});
              toyList.Add(new Toy {ID = 2, Price = 10, Color = "White"});
              toyList.Add(new Toy {ID = 3, Price = 10, Color = "Black"});
              }

              public string this[int toyId, string toyProperty]
              {
              get{return listOfProducts.FirstOrDefault(prod => prod.Id == productId);}
              set{listOfProducts.FirstOrDefault(prod => prod.Id == productId).toyProperty = value;}
              }
              }

              I want to be able to dynamically choose which property to insert into my LINQ query inside of the Indexer's set property. That way I can set the Price or Color of the Toy object dynamically. I created the toyProperty parameter in the Indexer parameter list so that the code that will consume the Indexer will be able to pass a value to the toyProperty in the LINQ Query. The code consuming the Indexer will look something like the following

              public double price = txtPrice.Text;
              public string color = txtColor.Text;

              public Merchandise item = new Merchandise();
              //Change Price Dynamically
              item[2, "Price"].Price = price;

              //Change Color Dynamically
              item[2, "Color"].Color = color;

              My Lambda Expression inside the set property of the Indexer does not work of course but I wonder if it is missing something that could help to make it work.

              M Offline
              M Offline
              Matt T Heffron
              wrote on last edited by
              #6

              As the others have said, this is probably possible but almost certainly not advisable! You would lose type safety and compile-time checking for correct property identification, etc. Here are my initial thoughts on how I'd do this.

              public class Toy
              {
              // changing the ID is probably NOT a good idea.
              // put it onto the constructor
              public Toy(int id)
              {
              ID = id;
              }
              public int ID { get; private set; }
              // unless you need ID to be a property (like for data binding)
              // this might be a case for a public readonly field:
              // public readonly int ID;
              public double Price { get; set; }
              public string Color { get; set; }
              }

              public class Merchandise
              {
              public Dictionary<int, Toy> toys;
              public Merchandise()
              {
              var toyList = new List<Toy>();
              // presumably you're actually loading the real data from some other source...
              toyList.Add(new Toy {ID = 1, Price = 10, Color = "Red"});
              toyList.Add(new Toy {ID = 2, Price = 10, Color = "White"});
              toyList.Add(new Toy {ID = 3, Price = 10, Color = "Black"});
              toys = toyList.ToDictionary(t => t.ID);
              }

              public string this[int toyId]
              {
              get
              {
              Toy theToy;
              toys.TryGetValue(toyID, out theToy); // In this case we can ignore the return value
              return theToy;
              }
              }
              }

              Then the usage is:

              // this is CLEARLY going to fail!
              // You need to use double.TryParse(txtPrice.Text, ...) with appropriate error handling
              // to convert it from a string to a double!!!!!
              public double price = txtPrice.Text;
              public string color = txtColor.Text;

              public Merchandise item = new Merchandise();
              // Before you reference the .Price or .Color properties,
              // you need to validate that item[2] didn't return null!!!

              // What you had:

              //Change Price Dynamically
              // item[2, "Price"].Price = price;
              // this ^^^^^^^^^ was pointless since passing the property name to the indexer didn't accomplish anything
              item[2].Price = price; // with my indexer definition

              //Change Color Dynamically
              // item[2, "Color"].Color = color;
              // again ^^^^^^^^^ pointless
              item[2].Color = color;

              // Instead, more like:
              Toy theToy = item[2];
              if (theToy != null)
              {
              //Change Price Dynamically
              theToy.Price = price;
              //Change Color Dynamically
              theToy.Color = color;
              }
              else
              {
              // report the no such toy with that ID error !!
              }

              "Fairy tales do not tell children the dragon

              M 1 Reply Last reply
              0
              • M Matt T Heffron

                As the others have said, this is probably possible but almost certainly not advisable! You would lose type safety and compile-time checking for correct property identification, etc. Here are my initial thoughts on how I'd do this.

                public class Toy
                {
                // changing the ID is probably NOT a good idea.
                // put it onto the constructor
                public Toy(int id)
                {
                ID = id;
                }
                public int ID { get; private set; }
                // unless you need ID to be a property (like for data binding)
                // this might be a case for a public readonly field:
                // public readonly int ID;
                public double Price { get; set; }
                public string Color { get; set; }
                }

                public class Merchandise
                {
                public Dictionary<int, Toy> toys;
                public Merchandise()
                {
                var toyList = new List<Toy>();
                // presumably you're actually loading the real data from some other source...
                toyList.Add(new Toy {ID = 1, Price = 10, Color = "Red"});
                toyList.Add(new Toy {ID = 2, Price = 10, Color = "White"});
                toyList.Add(new Toy {ID = 3, Price = 10, Color = "Black"});
                toys = toyList.ToDictionary(t => t.ID);
                }

                public string this[int toyId]
                {
                get
                {
                Toy theToy;
                toys.TryGetValue(toyID, out theToy); // In this case we can ignore the return value
                return theToy;
                }
                }
                }

                Then the usage is:

                // this is CLEARLY going to fail!
                // You need to use double.TryParse(txtPrice.Text, ...) with appropriate error handling
                // to convert it from a string to a double!!!!!
                public double price = txtPrice.Text;
                public string color = txtColor.Text;

                public Merchandise item = new Merchandise();
                // Before you reference the .Price or .Color properties,
                // you need to validate that item[2] didn't return null!!!

                // What you had:

                //Change Price Dynamically
                // item[2, "Price"].Price = price;
                // this ^^^^^^^^^ was pointless since passing the property name to the indexer didn't accomplish anything
                item[2].Price = price; // with my indexer definition

                //Change Color Dynamically
                // item[2, "Color"].Color = color;
                // again ^^^^^^^^^ pointless
                item[2].Color = color;

                // Instead, more like:
                Toy theToy = item[2];
                if (theToy != null)
                {
                //Change Price Dynamically
                theToy.Price = price;
                //Change Color Dynamically
                theToy.Color = color;
                }
                else
                {
                // report the no such toy with that ID error !!
                }

                "Fairy tales do not tell children the dragon

                M Offline
                M Offline
                MadDashCoder
                wrote on last edited by
                #7

                Thank all for your valuable inputs especially you Matt. The purpose of this project was just to explore how to dynamically choose a property to be inserted into a LINQ query at runtime. I've learned a lot from everyone's input. I was able to do what I had originally set out to do using the code below although it is not as elegant as your solution.

                public string this[int toyId, string price, string color]
                {
                get
                {
                string result = string.Empty;
                if (color != null)
                {
                result = toyList.FirstOrDefault(toy => toy.ID == toyId).Color;
                }
                else if (price != null)
                {
                result = (toyList.FirstOrDefault(toy => toy.ID == toyId).Price).ToString();
                }
                return result;
                }
                set
                {
                if (color != null)
                {
                toyList.FirstOrDefault(toy => toy.ID == toyId).Color = value;
                }
                else if (price != null)
                {
                toyList.FirstOrDefault(toy => toy.ID == toyId).Price = Convert.ToDouble(value);
                }
                }
                }

                M 1 Reply Last reply
                0
                • M MadDashCoder

                  Thank all for your valuable inputs especially you Matt. The purpose of this project was just to explore how to dynamically choose a property to be inserted into a LINQ query at runtime. I've learned a lot from everyone's input. I was able to do what I had originally set out to do using the code below although it is not as elegant as your solution.

                  public string this[int toyId, string price, string color]
                  {
                  get
                  {
                  string result = string.Empty;
                  if (color != null)
                  {
                  result = toyList.FirstOrDefault(toy => toy.ID == toyId).Color;
                  }
                  else if (price != null)
                  {
                  result = (toyList.FirstOrDefault(toy => toy.ID == toyId).Price).ToString();
                  }
                  return result;
                  }
                  set
                  {
                  if (color != null)
                  {
                  toyList.FirstOrDefault(toy => toy.ID == toyId).Color = value;
                  }
                  else if (price != null)
                  {
                  toyList.FirstOrDefault(toy => toy.ID == toyId).Price = Convert.ToDouble(value);
                  }
                  }
                  }

                  M Offline
                  M Offline
                  Matt T Heffron
                  wrote on last edited by
                  #8

                  This still suffers from the problems that I mentioned. It isn't even close to type-safe. You'll get a NullReferenceException if the toyId isn't found, unless both price and color are null, in which case you'll never know! For the "price" case, if the string is not a valid double, it will throw a FormatException (or, less likely, OverflowException). This is the wrong place in a design to be parsing the price value string to double! It ought to be done as near as possible to where the user provides the input so it can be reported appropriately. Finally, in fact, you did not "dynamically choose a property to be inserted into a LINQ query at runtime". You're choosing different properties of the result of identical LINQ queries based on boolean conditions represented by string values being null or not. I would consider this abuse of the indexer to gain a syntactic shortcut of very dubious value. So lesson learned. Don't do this in production code! (Or any code! ;) ) This is serious "code smell". I'm sorry, but it needed to be said. X|

                  "Fairy tales do not tell children the dragons exist. Children already know that dragons exist. Fairy tales tell children the dragons can be killed." - G.K. Chesterton

                  1 Reply Last reply
                  0
                  • M MadDashCoder

                    Suppose I have 2 objects like the following

                    public class Toy
                    {
                    public int ID{get;set;}
                    public double Price{get;set;}
                    public sting Color{get; set;}
                    }
                    public class Merchandise
                    {
                    public List toyList;
                    public Merchandise()
                    {
                    toyList= new List();
                    toyList.Add(new Toy {ID = 1, Price = 10, Color = "Red"});
                    toyList.Add(new Toy {ID = 2, Price = 10, Color = "White"});
                    toyList.Add(new Toy {ID = 3, Price = 10, Color = "Black"});
                    }

                    public string this[int toyId, string toyProperty]
                    {
                    get{return listOfProducts.FirstOrDefault(prod => prod.Id == productId);}
                    set{listOfProducts.FirstOrDefault(prod => prod.Id == productId).toyProperty = value;}
                    }
                    }

                    I want to be able to dynamically choose which property to insert into my LINQ query inside of the Indexer's set property. That way I can set the Price or Color of the Toy object dynamically. I created the toyProperty parameter in the Indexer parameter list so that the code that will consume the Indexer will be able to pass a value to the toyProperty in the LINQ Query. The code consuming the Indexer will look something like the following

                    public double price = txtPrice.Text;
                    public string color = txtColor.Text;

                    public Merchandise item = new Merchandise();
                    //Change Price Dynamically
                    item[2, "Price"].Price = price;

                    //Change Color Dynamically
                    item[2, "Color"].Color = color;

                    My Lambda Expression inside the set property of the Indexer does not work of course but I wonder if it is missing something that could help to make it work.

                    L Offline
                    L Offline
                    Lost User
                    wrote on last edited by
                    #9

                    Restated another way, the question is how to update an existing item in a collection using LINQ:

                         List toys = new List();
                         toys.Add( new Toy() { Id = 1, Color = "Red", Price = 1.20M } );
                         toys.Add( new Toy() { Id = 2, Color = "Red", Price = 1.20M } );
                         toys.Add( new Toy() { Id = 3, Color = "Red", Price = 1.20M } );
                    
                         toys.Single( o => o.Id == 2 ).Color = "Blue";
                         toys.Single( o => o.Id == 2 ).Price = 3.99M;
                    
                         toys.ForEach( o => Console.WriteLine( $"{o.Id} {o.Color} {o.Price}" ) );
                    
                    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