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 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 Online
                      realJSOPR Online
                      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