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. The Lounge
  3. That moment when a lot of difficult work becomes a five minute job...

That moment when a lot of difficult work becomes a five minute job...

Scheduled Pinned Locked Moved The Lounge
csharpjavascriptlinqasp-netdatabase
15 Posts 9 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.
  • Sander RosselS Offline
    Sander RosselS Offline
    Sander Rossel
    wrote on last edited by
    #1

    So I wanted to combine two select expressions in EF Core 2.0. Something like context.MyTable.Select(e => new TModel { ... }).Select(additionalSelector).ToList(); Now that's just not possible, because the first Select converts the query to IQueryable and the second Select has no reference to the entity (unless I put it in the model, not sure if that works, but I don't want to anyway). So I found myself "merging" two select expressions which went awry because the "e" in additionalSelector isn't the same "e" as in the original selector [read: reference to ParameterExpression]. And Expressions are immutable... :sigh: So I wanted to start by converting the entire tree manually (and probably drop the idea because that isn't worth it) when I found the ExpressionVisitor[^]. All that manual work pretty much became:

    public class ExpressionParameterSwitcher : ExpressionVisitor
    {
        private readonly ParameterExpression parameter;
    
        public ExpressionParameterSwitcher(ParameterExpression parameter)
        {
            this.parameter = parameter;
        }
        protected override Expression VisitParameter(ParameterExpression node)
        {
            return parameter;
        }
    }
    

    Good times :D Thought I'd post it here in case anyone ever needs it and, like me, didn't know about the ExpressionVisitor.

    Best, Sander Continuous Integration, Delivery, and Deployment arrgh.js - Bringing LINQ to JavaScript Object-Oriented Programming in C# Succinctly

    M R M J S 5 Replies Last reply
    0
    • Sander RosselS Sander Rossel

      So I wanted to combine two select expressions in EF Core 2.0. Something like context.MyTable.Select(e => new TModel { ... }).Select(additionalSelector).ToList(); Now that's just not possible, because the first Select converts the query to IQueryable and the second Select has no reference to the entity (unless I put it in the model, not sure if that works, but I don't want to anyway). So I found myself "merging" two select expressions which went awry because the "e" in additionalSelector isn't the same "e" as in the original selector [read: reference to ParameterExpression]. And Expressions are immutable... :sigh: So I wanted to start by converting the entire tree manually (and probably drop the idea because that isn't worth it) when I found the ExpressionVisitor[^]. All that manual work pretty much became:

      public class ExpressionParameterSwitcher : ExpressionVisitor
      {
          private readonly ParameterExpression parameter;
      
          public ExpressionParameterSwitcher(ParameterExpression parameter)
          {
              this.parameter = parameter;
          }
          protected override Expression VisitParameter(ParameterExpression node)
          {
              return parameter;
          }
      }
      

      Good times :D Thought I'd post it here in case anyone ever needs it and, like me, didn't know about the ExpressionVisitor.

      Best, Sander Continuous Integration, Delivery, and Deployment arrgh.js - Bringing LINQ to JavaScript Object-Oriented Programming in C# Succinctly

      M Offline
      M Offline
      Marc Clifton
      wrote on last edited by
      #2

      How did you ever find that? And how did you figure out how it works from the incredibly sparse MSDN documentation? I found what looks like a [decent tutorial](http://pelebyte.net/blog/2011/05/13/doing-simple-things-with-expressionvisitor/), of course not by MS, which I'll have to read through now.

      Latest Article - Contextual Data Explorer Learning to code with python is like learning to swim with those little arm floaties. It gives you undeserved confidence and will eventually drown you. - DangerBunny Artificial intelligence is the only remedy for natural stupidity. - CDP1802

      Sander RosselS 1 Reply Last reply
      0
      • Sander RosselS Sander Rossel

        So I wanted to combine two select expressions in EF Core 2.0. Something like context.MyTable.Select(e => new TModel { ... }).Select(additionalSelector).ToList(); Now that's just not possible, because the first Select converts the query to IQueryable and the second Select has no reference to the entity (unless I put it in the model, not sure if that works, but I don't want to anyway). So I found myself "merging" two select expressions which went awry because the "e" in additionalSelector isn't the same "e" as in the original selector [read: reference to ParameterExpression]. And Expressions are immutable... :sigh: So I wanted to start by converting the entire tree manually (and probably drop the idea because that isn't worth it) when I found the ExpressionVisitor[^]. All that manual work pretty much became:

        public class ExpressionParameterSwitcher : ExpressionVisitor
        {
            private readonly ParameterExpression parameter;
        
            public ExpressionParameterSwitcher(ParameterExpression parameter)
            {
                this.parameter = parameter;
            }
            protected override Expression VisitParameter(ParameterExpression node)
            {
                return parameter;
            }
        }
        

        Good times :D Thought I'd post it here in case anyone ever needs it and, like me, didn't know about the ExpressionVisitor.

        Best, Sander Continuous Integration, Delivery, and Deployment arrgh.js - Bringing LINQ to JavaScript Object-Oriented Programming in C# Succinctly

        R Offline
        R Offline
        RickZeeland
        wrote on last edited by
        #3

        Looks like stuff for an upcoming article :thumbsup:

        Sander RosselS 1 Reply Last reply
        0
        • Sander RosselS Sander Rossel

          So I wanted to combine two select expressions in EF Core 2.0. Something like context.MyTable.Select(e => new TModel { ... }).Select(additionalSelector).ToList(); Now that's just not possible, because the first Select converts the query to IQueryable and the second Select has no reference to the entity (unless I put it in the model, not sure if that works, but I don't want to anyway). So I found myself "merging" two select expressions which went awry because the "e" in additionalSelector isn't the same "e" as in the original selector [read: reference to ParameterExpression]. And Expressions are immutable... :sigh: So I wanted to start by converting the entire tree manually (and probably drop the idea because that isn't worth it) when I found the ExpressionVisitor[^]. All that manual work pretty much became:

          public class ExpressionParameterSwitcher : ExpressionVisitor
          {
              private readonly ParameterExpression parameter;
          
              public ExpressionParameterSwitcher(ParameterExpression parameter)
              {
                  this.parameter = parameter;
              }
              protected override Expression VisitParameter(ParameterExpression node)
              {
                  return parameter;
              }
          }
          

          Good times :D Thought I'd post it here in case anyone ever needs it and, like me, didn't know about the ExpressionVisitor.

          Best, Sander Continuous Integration, Delivery, and Deployment arrgh.js - Bringing LINQ to JavaScript Object-Oriented Programming in C# Succinctly

          M Offline
          M Offline
          Matthew Dennis
          wrote on last edited by
          #4

          Is the additional info coming from the same entity. If so, why not just add it to TModel and get it with the first select?

          "Time flies like an arrow. Fruit flies like a banana."

          Sander RosselS 1 Reply Last reply
          0
          • M Marc Clifton

            How did you ever find that? And how did you figure out how it works from the incredibly sparse MSDN documentation? I found what looks like a [decent tutorial](http://pelebyte.net/blog/2011/05/13/doing-simple-things-with-expressionvisitor/), of course not by MS, which I'll have to read through now.

            Latest Article - Contextual Data Explorer Learning to code with python is like learning to swim with those little arm floaties. It gives you undeserved confidence and will eventually drown you. - DangerBunny Artificial intelligence is the only remedy for natural stupidity. - CDP1802

            Sander RosselS Offline
            Sander RosselS Offline
            Sander Rossel
            wrote on last edited by
            #5

            You just have to read between the lines on the MSDN page! :laugh: Just kidding, I Googled for expression tree change parameter - Google Search[^] and my first hit was c# - How to change a type in an expression tree? - Stack Overflow[^]. I didn't actually use the MSDN documentation, but thought I'd leave that here as "official" reference :laugh: I had to change the code I posted above just a little by the way, I only need to change the parameter if the parameter's type is the same as the node's type (or it'll mess up your tree pretty bad).

            Best, Sander Continuous Integration, Delivery, and Deployment arrgh.js - Bringing LINQ to JavaScript Object-Oriented Programming in C# Succinctly

            1 Reply Last reply
            0
            • R RickZeeland

              Looks like stuff for an upcoming article :thumbsup:

              Sander RosselS Offline
              Sander RosselS Offline
              Sander Rossel
              wrote on last edited by
              #6

              A tip at best... Between work, my own business, study for Azure exams, and something that more or less resembles a social life I have zero time to write at the moment :sigh:

              Best, Sander Continuous Integration, Delivery, and Deployment arrgh.js - Bringing LINQ to JavaScript Object-Oriented Programming in C# Succinctly

              R realJSOPR 2 Replies Last reply
              0
              • Sander RosselS Sander Rossel

                A tip at best... Between work, my own business, study for Azure exams, and something that more or less resembles a social life I have zero time to write at the moment :sigh:

                Best, Sander Continuous Integration, Delivery, and Deployment arrgh.js - Bringing LINQ to JavaScript Object-Oriented Programming in C# Succinctly

                R Offline
                R Offline
                RickZeeland
                wrote on last edited by
                #7

                Looks like we are in the same boat again (don't know if that's good English), time keeps on slippin, slippin, into the future ... :-\

                1 Reply Last reply
                0
                • M Matthew Dennis

                  Is the additional info coming from the same entity. If so, why not just add it to TModel and get it with the first select?

                  "Time flies like an arrow. Fruit flies like a banana."

                  Sander RosselS Offline
                  Sander RosselS Offline
                  Sander Rossel
                  wrote on last edited by
                  #8

                  It's actually more like context.Set().Select(e => new TModel { ... }).ToList(); And now I want to "open up" the selector, not completely replace it (because that will result in quite some duplicated code), but add to it. I have x TEntity classes that share stuff like Id, Name, Active and even a details table reference, that go nicely into the common selector. But some also have one or two properties that aren't shared by the others. Other than those few properties all logic is exactly the same. I currently have five web pages that use the exact same code in the back-end (save for those few properties) :D Took me about twenty to thirty hours to write the first page as abstract as it is and then it took me an hour to add three more and I just spend four hours for the fifth, for which I had to add this :laugh:

                  Best, Sander Continuous Integration, Delivery, and Deployment arrgh.js - Bringing LINQ to JavaScript Object-Oriented Programming in C# Succinctly

                  L 1 Reply Last reply
                  0
                  • Sander RosselS Sander Rossel

                    It's actually more like context.Set().Select(e => new TModel { ... }).ToList(); And now I want to "open up" the selector, not completely replace it (because that will result in quite some duplicated code), but add to it. I have x TEntity classes that share stuff like Id, Name, Active and even a details table reference, that go nicely into the common selector. But some also have one or two properties that aren't shared by the others. Other than those few properties all logic is exactly the same. I currently have five web pages that use the exact same code in the back-end (save for those few properties) :D Took me about twenty to thirty hours to write the first page as abstract as it is and then it took me an hour to add three more and I just spend four hours for the fifth, for which I had to add this :laugh:

                    Best, Sander Continuous Integration, Delivery, and Deployment arrgh.js - Bringing LINQ to JavaScript Object-Oriented Programming in C# Succinctly

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

                    You could do something with the Join method but I would derive an new model from TModel. There are a number of ways to do what you want, but without seeing your existing code, I can't suggest the best way. You really want this to only make one call to the database, so getting the right projection in the first place is important.

                    Sander RosselS 1 Reply Last reply
                    0
                    • Sander RosselS Sander Rossel

                      So I wanted to combine two select expressions in EF Core 2.0. Something like context.MyTable.Select(e => new TModel { ... }).Select(additionalSelector).ToList(); Now that's just not possible, because the first Select converts the query to IQueryable and the second Select has no reference to the entity (unless I put it in the model, not sure if that works, but I don't want to anyway). So I found myself "merging" two select expressions which went awry because the "e" in additionalSelector isn't the same "e" as in the original selector [read: reference to ParameterExpression]. And Expressions are immutable... :sigh: So I wanted to start by converting the entire tree manually (and probably drop the idea because that isn't worth it) when I found the ExpressionVisitor[^]. All that manual work pretty much became:

                      public class ExpressionParameterSwitcher : ExpressionVisitor
                      {
                          private readonly ParameterExpression parameter;
                      
                          public ExpressionParameterSwitcher(ParameterExpression parameter)
                          {
                              this.parameter = parameter;
                          }
                          protected override Expression VisitParameter(ParameterExpression node)
                          {
                              return parameter;
                          }
                      }
                      

                      Good times :D Thought I'd post it here in case anyone ever needs it and, like me, didn't know about the ExpressionVisitor.

                      Best, Sander Continuous Integration, Delivery, and Deployment arrgh.js - Bringing LINQ to JavaScript Object-Oriented Programming in C# Succinctly

                      J Offline
                      J Offline
                      Jorgen Andersson
                      wrote on last edited by
                      #10

                      Bookmarked. This might come in handy if i ever rebuild my caching class. I just wish you could've given the thread a more descriptive name, next time I see it among the bookmarks I won't have a clue what it is about. :)

                      Wrong is evil and must be defeated. - Jeff Ello

                      1 Reply Last reply
                      0
                      • Sander RosselS Sander Rossel

                        A tip at best... Between work, my own business, study for Azure exams, and something that more or less resembles a social life I have zero time to write at the moment :sigh:

                        Best, Sander Continuous Integration, Delivery, and Deployment arrgh.js - Bringing LINQ to JavaScript Object-Oriented Programming in C# Succinctly

                        realJSOPR Offline
                        realJSOPR Offline
                        realJSOP
                        wrote on last edited by
                        #11

                        That's what I was gonna suggest - make it a tip/trick.

                        ".45 ACP - because shooting twice is just silly" - JSOP, 2010
                        -----
                        You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010
                        -----
                        When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013

                        1 Reply Last reply
                        0
                        • Sander RosselS Sander Rossel

                          So I wanted to combine two select expressions in EF Core 2.0. Something like context.MyTable.Select(e => new TModel { ... }).Select(additionalSelector).ToList(); Now that's just not possible, because the first Select converts the query to IQueryable and the second Select has no reference to the entity (unless I put it in the model, not sure if that works, but I don't want to anyway). So I found myself "merging" two select expressions which went awry because the "e" in additionalSelector isn't the same "e" as in the original selector [read: reference to ParameterExpression]. And Expressions are immutable... :sigh: So I wanted to start by converting the entire tree manually (and probably drop the idea because that isn't worth it) when I found the ExpressionVisitor[^]. All that manual work pretty much became:

                          public class ExpressionParameterSwitcher : ExpressionVisitor
                          {
                              private readonly ParameterExpression parameter;
                          
                              public ExpressionParameterSwitcher(ParameterExpression parameter)
                              {
                                  this.parameter = parameter;
                              }
                              protected override Expression VisitParameter(ParameterExpression node)
                              {
                                  return parameter;
                              }
                          }
                          

                          Good times :D Thought I'd post it here in case anyone ever needs it and, like me, didn't know about the ExpressionVisitor.

                          Best, Sander Continuous Integration, Delivery, and Deployment arrgh.js - Bringing LINQ to JavaScript Object-Oriented Programming in C# Succinctly

                          S Offline
                          S Offline
                          Slow Eddie
                          wrote on last edited by
                          #12

                          I have experienced the opposite quite often. You know, "that moment you realize that what you thought would be a five minute task, is turning into a lot of work". :sigh: :confused::mad:

                          "Newer" is NOT automatically better, only Different. (And more complex and bug ridden when it comes to all of the "boutique" languages / frameworks out there)

                          Sander RosselS 1 Reply Last reply
                          0
                          • S Slow Eddie

                            I have experienced the opposite quite often. You know, "that moment you realize that what you thought would be a five minute task, is turning into a lot of work". :sigh: :confused::mad:

                            "Newer" is NOT automatically better, only Different. (And more complex and bug ridden when it comes to all of the "boutique" languages / frameworks out there)

                            Sander RosselS Offline
                            Sander RosselS Offline
                            Sander Rossel
                            wrote on last edited by
                            #13

                            That's also very familiar :laugh:

                            Best, Sander Continuous Integration, Delivery, and Deployment arrgh.js - Bringing LINQ to JavaScript Object-Oriented Programming in C# Succinctly

                            S 1 Reply Last reply
                            0
                            • L Lost User

                              You could do something with the Join method but I would derive an new model from TModel. There are a number of ways to do what you want, but without seeing your existing code, I can't suggest the best way. You really want this to only make one call to the database, so getting the right projection in the first place is important.

                              Sander RosselS Offline
                              Sander RosselS Offline
                              Sander Rossel
                              wrote on last edited by
                              #14

                              Matthew@Home wrote:

                              but without seeing your existing code, I can't suggest the best way

                              Well, I wasn't really asking for suggestions, but I appreciate the help :) Here's the situation: I've got a couple of entities.

                              public class EntityA : IMyInterface
                              {
                              public int Id { get; set; }
                              public string Name { get; set; }
                              public bool Active { get; set; }
                              public List Details { get; set; }
                              }

                              public class EntityB : IMyInterface
                              {
                              public int Id { get; set; }
                              public string Name { get; set; }
                              public bool Active { get; set; }
                              public List Details { get; set; }
                              }

                              public class EntityC : IMyInterface
                              {
                              public int Id { get; set; }
                              public string Name { get; set; }
                              public bool Active { get; set; }
                              public string SomeOtherProperty { get; set; }
                              public string AnotherProperty { get; set; }
                              public List Details { get; set; }
                              }

                              // Details all pretty much look the same as well, I've got more entities...

                              Then I've got this model:

                              public class SharedModel
                              {
                              public int Id { get; set; }
                              public string Name { get; set; }
                              public bool Active { get; set; }
                              public List Details { get; set; }
                              }

                              And a query for all entities:

                              public TModel GetModels()
                              where TModel : SharedModel, new()
                              where TEntity : class, IMyInterface, new()
                              {
                              context.Set()
                              .Where(...)
                              .Select(e => new TModel
                              {
                              Id = e.Id,
                              Name = e.Name,
                              Active = e.Active,
                              Details = e.Details.Select(...)
                              }).ToList();
                              }

                              So this works for everything except SomeOtherProperty and AnotherProperty for EntityC. So I somehow want to inject them into the selector.

                              Expression> baseSelect = e => new TModel
                              {
                              Id = e.Id,
                              Name = e.Name,
                              Active = e.Active,
                              Details = e.Details.Select(...)
                              };

                              // And in inherited class, call GetModels().
                              // Use this as parameter.
                              Expression> additionalSelect = e => new MyCustomModel
                              {
                              SomeOtherProperty = e.SomeOtherProperty,
                              AnotherProperty = e.AnotherProperty
                              };

                              And then merge the two trees...

                              MemberInitExpression baseSelectBody = (MemberInitExpression)baseSelect.Body;
                              MemberInitExpression additionalSelectBody

                              1 Reply Last reply
                              0
                              • Sander RosselS Sander Rossel

                                That's also very familiar :laugh:

                                Best, Sander Continuous Integration, Delivery, and Deployment arrgh.js - Bringing LINQ to JavaScript Object-Oriented Programming in C# Succinctly

                                S Offline
                                S Offline
                                Sundance Kid
                                wrote on last edited by
                                #15

                                Yip.. something that should be fast takes forever. Uhg And then having to explain to management :doh: why...

                                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