System.Runtime Schema: Resolving references using ‘binding context’


In my previous post “Assembly, Type and Method References”, I talked about how AssemblyReferences, TypeReferences and MethodReferences entities can be used to find references across assemblies, types and methods.


Context


Binding Context is a unique concept in SSMoS System.Runtime model and provides a resolution for the types and methods that are referenced between the assemblies AND loaded into the repository.  This allows you to navigate the references between assemblies faster than having to use a name-based approach for finding references.  


Let me walk you through a scenario:


·         FooAssembly.dll depends on BarAssembly.dll, because a type Foo in FooAssembly.dll references a type Bar in BarAssembly.dll


·         Both FooAssembly.dll and BarAssembly.dll have been loaded into the repository


How would you write this query – “Show all dependent assemblies for FooAssembly.dll that are also loaded into the repository”?  If you just wanted to find out the references, you can easily obtain that by querying the AssemblyReferences entity, but having a reference in that table doesn’t necessarily mean the metadata for that assembly is also available into the repository.    To try with some of our internal assemblies, I loaded Microsoft.M.LanguageServices.dll into the repository. 


The following T-SQL queries for all assembly references for Microsoft.M.LanguageServices that begin with “Microsoft.*”:


Select AR.* from [Repository].[System_Runtime].[AssemblyReferences] AS AR


INNER JOIN [Repository].[System_Runtime].[Assemblies] AS A ON A.Id = AR.Assembly


WHERE A.Name = ‘Microsoft.M.LanguageServices’ AND AR.Name LIKE ‘Microsoft.%’


The result set looks like this on my machine:




































































































Folder


Id


Name


VersionMajor


VersionMinor


VersionRevision


VersionBuild


Culture


PublicKeyToken


Assembly


Hash_Name


117


16


Microsoft.Intellipad.Core


1


0


0


0


 


0x31BF3856AD364E35


2


366780607


117


18


Microsoft.M


1


0


0


0


 


0x31BF3856AD364E35


2


2078358469


117


19


Microsoft.Intellipad.Editor


1


0


0


0


 


0x31BF3856AD364E35


2


-1383118891


117


22


Microsoft.Oslo.Internal


1


0


0


0


 


0x31BF3856AD364E35


2


791105609


117


25


Microsoft.Build.Engine


4


0


0


0


 


0xB03F5F7F11D50A3A


2


1222306620


117


27


Microsoft.Intellipad.Framework


1


0


0


0


 


0x31BF3856AD364E35


2


988212485


117


33


Microsoft.Build.Framework


4


0


0


0


 


0xB03F5F7F11D50A3A


2


899350863


 


But what this query doesn’t tell me yet is whether or not the dependent assemblies are also loaded into the repository.  To find that I need to look into Assemblies table for existence of Microsoft.M.dll assembly that matches the identity of assembly being referenced (i.e. Name + Version + PublicKeyToken + Culture).  Here is the revised query (this only matches based on the assembly name for now).         


Select AR.* from [Repository].[System_Runtime].[AssemblyReferences] AS AR


INNER JOIN [Repository].[System_Runtime].[Assemblies] AS A ON A.Id = AR.Assembly


INNER JOIN [Repository].[System_Runtime].[Assemblies] AS A2 ON ( A2.Name = AR.Name )


WHERE A.Name = ‘Microsoft.M.LanguageServices’ AND AR.Name LIKE ‘Microsoft.%’


The result set of this query is only one row, because I only loaded Microsoft.M.dll into the database.




























Folder


Id


Name


VersionMajor


VersionMinor


VersionRevision


VersionBuild


Culture


PublicKeyToken


Assembly


Hash_Name


117


18


Microsoft.M


1


0


0


0


 


0x31BF3856AD364E35


2


2078358469


 


The Binding Context concept lets the system do the assembly name-matching for you and populate a bunch of tables which you can directly query to find answers.   The above query can be re-written like this using the BindingContext and yields the same result. 


SELECT AR.* FROM [Repository].[System_Runtime].[AssemblyReferences] AS AR


INNER JOIN [Repository].[System_Runtime].[Assemblies] AS A ON A.Id = AR.Assembly


WHERE AR.Id IN


   (SELECT BAR.SourceAssemblyReference FROM [Repository].[System_Runtime].[BoundAssemblyReferences] AS BAR)


Did you notice that we didn’t have to specify the name matching in above query? The system takes care of that.


Binding Context Overview


Binding Context makes it easier to write dependency queries to resolve type/method references to the type/method definition in the repository.  The following diagram shows the high level relationship between core entities related to the Binding Context.




 


n  BindingContexts


o   Holds individual binding context for a group of assemblies that make a particular application.  For example, you may want to create separate binding contexts for each individual tier in your application.  3rd party  libraries may themselves be loaded into a binding context of their own.


 


n  BindingContextAssemblies


o   Holds links to each assemblies that are part of the binding context


 


n  BoundAssemblyReferences


o   Provides resolution between assembly references and assemblies


o   System populates this table when assemblies are inserted into BindingContextAssemblies table


 


n  BoundTypeReferences


o   Provides resolution between type references (TypeReferences) and type definitions (TypeDefinitions)


o   System populates this table when assemblies are inserted into BindingContextAssemblies table


 


n  BoundMethodReferences


o   Provides resolution between method references (MethodReferences) and method definitions (MethodDefinitions)


o   System populates this table when assemblies are inserted into BindingContextAssemblies table


Before the binding context can be used, you need to:
















#


Description


T-SQL


1


Create a new binding context


— 117 = Folder ID


INSERT INTO [Repository].[System_Runtime].BindingContexts (Folder, Name)


VALUES (117, ‘Test’)


2


Insert assemblies into the binding context


— 3 = Binding Context ID, 1 = Assembly ID


INSERT INTO [Repository].[System_Runtime].BindingContextAssemblies (Folder, Context, Assembly)


VALUES (117, 3, 2)


 


The insert of assemblies into the binding context invokes a trigger that resolves type and method references between assemblies and populate BoundAssemblyReferences, BoundTypeReferences and BoundMethodReferences entities.


Once the assemblies are loaded into the binding context, you can perform queries like these. 


For following queries, I have already oaded m.exe, Microsoft.M.dll and Microsoft.Oslo.Internal.dll into the repository and into a binding context 3. 


Show all methods that are bound to and being referenced in m.exe assembly


SELECT A.Name AS SourceAssembly, A2.Name AS ReferencedAssembly, M2.Name AS ReferencedMethod


FROM [Repository].System_Runtime.BoundMethodReferences AS BMR


INNER JOIN [Repository].System_Runtime.Methods AS M ON M.Id = BMR.SourceMethodReference


INNER JOIN [Repository].System_Runtime.TypeReferences AS TR ON TR.Id = M.DeclaringType


INNER JOIN [Repository].System_Runtime.AssemblyReferences AS AR ON TR.AssemblyReference = AR.Id


INNER JOIN [Repository].System_Runtime.Assemblies AS A ON AR.Assembly = A.Id


INNER JOIN [Repository].System_Runtime.Methods AS M2 ON M2.Id = BMR.TargetMethodDefinition


INNER JOIN [Repository].System_Runtime.Types AS T ON M2.DeclaringType = T.Id


INNER JOIN [Repository].System_Runtime.Modules AS MO ON T.Module = MO.Id


INNER JOIN [Repository].System_Runtime.Assemblies AS A2 ON MO.Assembly = A2.Id


WHERE BMR.Context = 3 AND A.Name = ‘m’


Here is partial result for abovementioned query.  





























SourceAssembly


ReferencedAssembly


ReferencedMethod


m


Microsoft.Oslo.Internal


.ctor


m


Microsoft.Oslo.Internal


ParseForConsoleApplication


m


Microsoft.Oslo.Internal


AddParameterHelp


m


Microsoft.M


.ctor


m


Microsoft.M


ProcessInputLists


You can extend above query to see all methods in assembly m.exe that are calling methods defined in other assemblies loaded into the database.


SELECT A.Name AS SourceAssembly, M3.Name AS SourceMethod, A2.Name AS ReferencedAssembly, M2.Name AS ReferencedMethod


FROM [Repository].System_Runtime.BoundMethodReferences AS BMR


INNER JOIN [Repository].System_Runtime.Methods AS M ON M.Id = BMR.SourceMethodReference


INNER JOIN [Repository].System_Runtime.TypeReferences AS TR ON TR.Id = M.DeclaringType


INNER JOIN [Repository].System_Runtime.AssemblyReferences AS AR ON TR.AssemblyReference = AR.Id


INNER JOIN [Repository].System_Runtime.Assemblies AS A ON AR.Assembly = A.Id


INNER JOIN [Repository].System_Runtime.Methods AS M2 ON M2.Id = BMR.TargetMethodDefinition


INNER JOIN [Repository].System_Runtime.Types AS T ON M2.DeclaringType = T.Id


INNER JOIN [Repository].System_Runtime.Modules AS MO ON T.Module = MO.Id


INNER JOIN [Repository].System_Runtime.Assemblies AS A2 ON MO.Assembly = A2.Id


INNER JOIN [Repository].System_Runtime.CalledMethods AS CM ON CM.Callee = BMR.SourceMethodReference


INNER JOIN [Repository].System_Runtime.Methods AS M3 ON M3.Id = CM.Caller


WHERE BMR.Context = 3 AND A.Name = ‘m’



































SourceAssembly


SourceMethod


ReferencedAssembly


ReferencedMethod


m


<ProcessCommandLineArguments>b__0


Microsoft.Oslo.Internal


.ctor


m


ProcessCommandLineArguments


Microsoft.Oslo.Internal


ParseForConsoleApplication


m


<ProcessCommandLineArguments>b__0


Microsoft.Oslo.Internal


AddParameterHelp


m


BuildCompilerOptions


Microsoft.M


.ctor


m


ProcessCommandLineArguments


Microsoft.M


ProcessInputLists


Since this post has already gotten too long, I will write more binding context related queries in a future post.   Here is one query that I have been planning on writing and I think the binding context can be useful there.  


“Find all methods in your application that are not being called, across all the assemblies in the database (i.e. find all dead methods)”


Summary


Binding Context entities in the System.Runtime schema provide a quicker way to go from a reference to its definition in the repository.  What do you think of the Binding Context set of entities in the System.Runtime schema? Do you think they can be useful for your query scenarios? Does the name binding context resonate?   We appreciate your feedback!

Comments (0)