none
RuntimeBinderException depending on what kind of project reference.

    Question


  • I've posted a question on StackOverflow and thought it'd also be worth posting it here. For what it's worth the original SO thread is here.

    I have spent the last couple of days refactoring a project. This project uses Dapper and the SqlMapper functionality to map the result of Sql queries onto objects. As part of my refactoring I moved some of the objects to a separate assembly and that's where things went a bit awry.
            public async Task<IEnumerable<HL7Control>> GetHl7ControlRecords()
            {
                _log.Info("Obtaining a list of required transfer service agents.");
    
                var agentList = StatementBuilder.BuildDapperGetAllHl7ControlRecords();
    
                return await SqlMapper.QueryAsync<HL7Control>(_db, agentList.Sql,agentList.Param);
            }
    
    This kept throwing a RuntimeBinder exception saying that 'QueryAsync<>' was not a member of SqlMapper. This is code that has been fine for over six months.

    I've finally tracked down the problem and I'd appreciate some thoughts from others. The 'solution' is to replace project references to the assembly containing 'HL7Control' with browse references (ie; `<Project Reference Include...>` becomes `<Reference Include...>` in the project file.

    The solution is being built by vs2015 and targets .NET4.6 except for the new assembly that targets .NET4.0.

    AgentList is not only badly named but is actually a class:
        public class DapperStatement
        {
            public string Sql { get;  }
    
            public dynamic Param { get; }
    
            public DapperStatement(string sql, dynamic param)
            {
                Sql = sql;
                Param = param;
            }
        }
    
    And it's because Param is a dynamic that the RuntimeBinder is involved. Now I know that dynamic doesn't cross assembly boundaries and that is something else I had to address during this refactoring. But in this case although DapperStatement is defined in a different assembly the object instance is not passing across an assembly boundary. And DapperStatement always was in another assembly to where it's used.

    Also note that SqlMapper.Query<> always works so apparently being async is a factor in this.

    I also rebooted my machine overnight and rebuilt from scratch and the issue remains.

    Changing the new assembly to be .NET4.6 doesn't change anything (other than breaking the external client project that it is being developed for, lol).


    I have spent the last couple of days refactoring a project. This project uses Dapper and the SqlMapper functionality to map the result of Sql queries onto objects. As part of my refactoring I moved some of the objects to a separate assembly and that's where things went a bit awry.

        public async Task<IEnumerable<HL7Control>> GetHl7ControlRecords()
        {
            _log.Info("Obtaining a list of required transfer service agents.");
    
            var agentList = StatementBuilder.BuildDapperGetAllHl7ControlRecords();
    
            return await SqlMapper.QueryAsync<HL7Control>(_db, agentList.Sql,agentList.Param);
        }
    

    This kept throwing a RuntimeBinder exception saying that 'QueryAsync<>' was not a member of SqlMapper. This is code that has been fine for over six months.

    I've finally tracked down the problem and I'd appreciate some thoughts from others. The 'solution' is to replace project references to the assembly containing 'HL7Control' with browse references (ie; <Project Reference Include...> becomes <Reference Include...> in the project file.

    The solution is being built by vs2015 and targets .NET4.6 except for the new assembly that targets .NET4.0.

    Any thoughts welcome as I'm not happy when I don't understand a 'fix'.

    Thanks.

    Edit: Some more info. I neglected to mention that agentList is not only badly named but is actually a class:

    public class DapperStatement
    {
        public string Sql { get;  }
    
        public dynamic Param { get; }
    
        public DapperStatement(string sql, dynamic param)
        {
            Sql = sql;
            Param = param;
        }
    }
    

    And it's because Param is a dynamic that the RuntimeBinder is involved. Now I know that dynamic doesn't cross assembly boundaries and that is something else I had to address during this refactoring. But in this case although DapperStatement is defined in a different assembly the object instance is not passing across an assembly boundary. And DapperStatement always was in another assembly to where it's used.

    Also note that SqlMapper.Query<> always works so apparently being async is a factor in this.

    I also rebooted my machine overnight and rebuilt from scratch and the issue remains.

    Oh and changing the new assembly to be .NET4.6 doesn't change anything (other than breaking the external client project that it is being developed for, lol).

    I have spent the last couple of days refactoring a project. This project uses Dapper and the SqlMapper functionality to map the result of Sql queries onto objects. As part of my refactoring I moved some of the objects to a separate assembly and that's where things went a bit awry.

        public async Task<IEnumerable<HL7Control>> GetHl7ControlRecords()
        {
            _log.Info("Obtaining a list of required transfer service agents.");
    
            var agentList = StatementBuilder.BuildDapperGetAllHl7ControlRecords();
    
            return await SqlMapper.QueryAsync<HL7Control>(_db, agentList.Sql,agentList.Param);
        }
    

    This kept throwing a RuntimeBinder exception saying that 'QueryAsync<>' was not a member of SqlMapper. This is code that has been fine for over six months.

    I've finally tracked down the problem and I'd appreciate some thoughts from others. The 'solution' is to replace project references to the assembly containing 'HL7Control' with browse references (ie; <Project Reference Include...> becomes <Reference Include...> in the project file.

    The solution is being built by vs2015 and targets .NET4.6 except for the new assembly that targets .NET4.0.

    Any thoughts welcome as I'm not happy when I don't understand a 'fix'.

    Thanks.

    Edit: Some more info. I neglected to mention that agentList is not only badly named but is actually a class:

    public class DapperStatement
    {
        public string Sql { get;  }
    
        public dynamic Param { get; }
    
        public DapperStatement(string sql, dynamic param)
        {
            Sql = sql;
            Param = param;
        }
    }
    

    And it's because Param is a dynamic that the RuntimeBinder is involved. Now I know that dynamic doesn't cross assembly boundaries and that is something else I had to address during this refactoring. But in this case although DapperStatement is defined in a different assembly the object instance is not passing across an assembly boundary. And DapperStatement always was in another assembly to where it's used.

    Also note that SqlMapper.Query<> always works so apparently being async is a factor in this.

    I also rebooted my machine overnight and rebuilt from scratch and the issue remains.

    Oh and changing the new assembly to be .NET4.6 doesn't change anything (other than breaking the external client project that it is being developed for, lol).

    I have spent the last couple of days refactoring a project. This project uses Dapper and the SqlMapper functionality to map the result of Sql queries onto objects. As part of my refactoring I moved some of the objects to a separate assembly and that's where things went a bit awry.

        public async Task<IEnumerable<HL7Control>> GetHl7ControlRecords()
        {
            _log.Info("Obtaining a list of required transfer service agents.");
    
            var agentList = StatementBuilder.BuildDapperGetAllHl7ControlRecords();
    
            return await SqlMapper.QueryAsync<HL7Control>(_db, agentList.Sql,agentList.Param);
        }
    

    This kept throwing a RuntimeBinder exception saying that 'QueryAsync<>' was not a member of SqlMapper. This is code that has been fine for over six months.

    I've finally tracked down the problem and I'd appreciate some thoughts from others. The 'solution' is to replace project references to the assembly containing 'HL7Control' with browse references (ie; <Project Reference Include...> becomes <Reference Include...> in the project file.

    The solution is being built by vs2015 and targets .NET4.6 except for the new assembly that targets .NET4.0.

    Any thoughts welcome as I'm not happy when I don't understand a 'fix'.

    Thanks.

    Edit: Some more info. I neglected to mention that agentList is not only badly named but is actually a class:

    public class DapperStatement
    {
        public string Sql { get;  }
    
        public dynamic Param { get; }
    
        public DapperStatement(string sql, dynamic param)
        {
            Sql = sql;
            Param = param;
        }
    }
    

    And it's because Param is a dynamic that the RuntimeBinder is involved. Now I know that dynamic doesn't cross assembly boundaries and that is something else I had to address during this refactoring. But in this case although DapperStatement is defined in a different assembly the object instance is not passing across an assembly boundary. And DapperStatement always was in another assembly to where it's used.

    Also note that SqlMapper.Query<> always works so apparently being async is a factor in this.

    I also rebooted my machine overnight and rebuilt from scratch and the issue remains.

    Oh and changing the new assembly to be .NET4.6 doesn't change anything (other than breaking the external client project that it is being developed for, lol).

    I have spent the last couple of days refactoring a project. This project uses Dapper and the SqlMapper functionality to map the result of Sql queries onto objects. As part of my refactoring I moved some of the objects to a separate assembly and that's where things went a bit awry.

        public async Task<IEnumerable<HL7Control>> GetHl7ControlRecords()
        {
            _log.Info("Obtaining a list of required transfer service agents.");
    
            var agentList = StatementBuilder.BuildDapperGetAllHl7ControlRecords();
    
            return await SqlMapper.QueryAsync<HL7Control>(_db, agentList.Sql,agentList.Param);
        }
    

    This kept throwing a RuntimeBinder exception saying that 'QueryAsync<>' was not a member of SqlMapper. This is code that has been fine for over six months.

    I've finally tracked down the problem and I'd appreciate some thoughts from others. The 'solution' is to replace project references to the assembly containing 'HL7Control' with browse references (ie; <Project Reference Include...> becomes <Reference Include...> in the project file.

    The solution is being built by vs2015 and targets .NET4.6 except for the new assembly that targets .NET4.0.

    Any thoughts welcome as I'm not happy when I don't understand a 'fix'.

    Thanks.

    Edit: Some more info. I neglected to mention that agentList is not only badly named but is actually a class:

    public class DapperStatement
    {
        public string Sql { get;  }
    
        public dynamic Param { get; }
    
        public DapperStatement(string sql, dynamic param)
        {
            Sql = sql;
            Param = param;
        }
    }
    

    And it's because Param is a dynamic that the RuntimeBinder is involved. Now I know that dynamic doesn't cross assembly boundaries and that is something else I had to address during this refactoring. But in this case although DapperStatement is defined in a different assembly the object instance is not passing across an assembly boundary. And DapperStatement always was in another assembly to where it's used.

    Also note that SqlMapper.Query<> always works so apparently being async is a factor in this.

    I also rebooted my machine overnight and rebuilt from scratch and the issue remains.

    Oh and changing the new assembly to be .NET4.6 doesn't change anything (other than breaking the external client project that it is being developed for, lol).

    I have spent the last couple of days refactoring a project. This project uses Dapper and the SqlMapper functionality to map the result of Sql queries onto objects. As part of my refactoring I moved some of the objects to a separate assembly and that's where things went a bit awry.

    public async Task<IEnumerable<HL7Control>> GetHl7ControlRecords()
        {
            _log.Info("Obtaining a list of required transfer service agents.");
    
            var agentList = StatementBuilder.BuildDapperGetAllHl7ControlRecords();
    
            return await SqlMapper.QueryAsync<HL7Control>(_db, agentList.Sql,agentList.Param);
        }
    

    This kept throwing a RuntimeBinder exception saying that 'QueryAsync<>' was not a member of SqlMapper. This is code that has been fine for over six months.

    I've finally tracked down the problem and I'd appreciate some thoughts from others. The 'solution' is to replace project references to the assembly containing 'HL7Control' with browse references (ie; <Project Reference Include...> becomes <Reference Include...> in the project file.

    The solution is being built by vs2015 and targets .NET4.6 except for the new assembly that targets .NET4.0.

    Any thoughts welcome as I'm not happy when I don't understand a 'fix'.

    Thanks.

    Edit: Some more info. I neglected to mention that agentList is not only badly named but is actually a class:

    public class DapperStatement
    {
        public string Sql { get;  }
    
        public dynamic Param { get; }
    
        public DapperStatement(string sql, dynamic param)
        {
            Sql = sql;
            Param = param;
        }
    }
    

    And it's because Param is a dynamic that the RuntimeBinder is involved. Now I know that dynamic doesn't cross assembly boundaries and that is something else I had to address during this refactoring. But in this case although DapperStatement is defined in a different assembly the object instance is not passing across an assembly boundary. And DapperStatement always was in another assembly to where it's used.

    Also note that SqlMapper.Query<> always works so apparently being async is a factor in this.

    I also rebooted my machine overnight and rebuilt from scratch and the issue remains.

    Oh and changing the new assembly to be .NET4.6 doesn't change anything (other than breaking the external client project that it is being developed for, lol).

    Wednesday, January 11, 2017 10:06 AM

Answers

  • Hi AndrueC,

    If you change the two class library A and B to use the same .NET Framework version, how about the result?

    I met an issue before: The same project met an issue if using different .NET Framework versions.

    For your issue, it is possible to refer to two .NET versions, but I think it also have a potential risk, I mean that if they use the same dll file/dependent assembly in two different class library or certain assembly has been updated/changed, it would have a risk, that's the reason I suggest you use the same version, debug it again, at least, we could narrow down this issue, do you agree with me?:)

    Best Regards,

    Jack


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by AndrueC Monday, January 16, 2017 11:31 AM
    Monday, January 16, 2017 11:00 AM
    Moderator

All replies

  • Hi AndrueC,

    >>I've finally tracked down the problem and I'd appreciate some thoughts from others. The 'solution' is to replace project references to the assembly containing 'HL7Control' with browse references (ie; `<Project Reference Include...>` becomes `<Reference Include...>` in the project file.

    The solution is being built by vs2015 and targets .NET4.6 except for the new assembly that targets .NET4.0.

    Based on your description, I've made a test on my local side.

    Test environment is VS2015 Enterprise and build target to .net 4.6.2

    1. Create a Workflow project
    2. Create a Classlibrary project
    3. Add Classllibrary project to WF project as a Project reference
    4. Open project file
     <ItemGroup>
        <ProjectReference Include="..\ClassLibrary1\ClassLibrary1.csproj">
          <Project>{0ab6c513-6e38-4705-9d30-7af6906007fc}</Project>
          <Name>ClassLibrary1</Name>
        </ProjectReference>
      </ItemGroup> 

    You'll find ProjectReference as above.

    From my test result. It works fine. Do I misunderstand you? If yes, please feel free to let me know.

    Best regards,

    Kristin



    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    • Edited by Kristin Xie Thursday, January 12, 2017 3:16 AM
    Thursday, January 12, 2017 3:15 AM
  • Unfortunately yes, there's a misunderstanding. This isn't about VS creating the wrong kind of reference. The issue is that I have to manually change the reference to be a browse reference for the code to run. I'm puzzled as to why that might be the case.

    My current suspicion is that it has something to do with the mix of framework versions but I haven't been able to prove it. What I have in the solution is:

    Class Library A - .NET4.0

    Class Library B - .NET4.6, depends on class Library B.

    Both libraries are dependant on Dapper. For some reason code in Class Library B can't call the Dapper .QueryAsync<> extension if a project reference is used instead of a browse reference.

    It seems to me that the RuntimeBinder is getting confused. I had a thought at home that maybe it's expecting the .NET4.6 version of Dapper but the project reference means final binaries get the .NET4.0 version? There's a couple of tests I could do around that.

    Thursday, January 12, 2017 8:31 AM
  • Hi Andruec,

    Sorry to misunderstood you.

    Thank you for visiting the MSDN forum. I’m afraid that it is not the correct forum about this issue, since this forum is to discuss Visual C#. I think your issue more related to project building issue. I am moving your question to the moderator forum ("Where is the forum for..?"). The owner of the forum will direct you to a right forum. Thanks for your understanding.

    Best regards,

    Kristin


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, January 13, 2017 7:03 AM
  • Hi AndrueC,

    If you change the two class library A and B to use the same .NET Framework version, how about the result?

    I met an issue before: The same project met an issue if using different .NET Framework versions.

    For your issue, it is possible to refer to two .NET versions, but I think it also have a potential risk, I mean that if they use the same dll file/dependent assembly in two different class library or certain assembly has been updated/changed, it would have a risk, that's the reason I suggest you use the same version, debug it again, at least, we could narrow down this issue, do you agree with me?:)

    Best Regards,

    Jack


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by AndrueC Monday, January 16, 2017 11:31 AM
    Monday, January 16, 2017 11:00 AM
    Moderator
  • Using the same .NET framework version did resolve the issue which means I think I know what's going on now. Unfortunately that's not a solution for us because we have to use both framework versions. What we are actually aiming for here is:

    Application A (.NET 4) depends on Class Library A (depends on Dapper .NET 4)

    Service/Application B (.NET 4.6) depends on Class Library B (depends on Dapper .NET 4.6). Class Library B depends on Class Library A (to avoid duplication of DB queries).

    When shipped Application A will have the Dapper .NET 4 assembly and the Service will have Dapper .NET 4.6.

    This arrangement is working when the two class libraries use browse references but not when they use project references. For some reason when using project references everything gets Dapper .NET 4 in its output folder which crashes the 4.6 builds at runtime.

    Mind you it's intriguing how the Service etc work with browse references since that gives us:

    Executable <- Class Library B (.NET 4.6) <- Class Library A (.NET 4) <- Dapper .NET 4.6.

    Anyway we've learnt something new about project references which is good. We also have something to help us move forward. The issue should go away soon anyway as Application A is being pensioned off and everything will then have moved to .NET4.6. We're also removing DB access from client-side completely.

    So thanks to all for your help.

    Monday, January 16, 2017 11:19 AM