Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

SQL Provider


Published on

Slides from the talk at Skillsmatter on my F# erasing SQL provider

Published in: Technology
  • Be the first to comment

SQL Provider

  1. 1. SQL Type Provider Ross McKinlay, January 2014 @pezi_pink
  2. 2. But….. We already have a SQL type provider!!!
  3. 3. • Only supports SQL Server • Supports any number of database vendors • Uses SQLMetal.exe to generate code • No code generation step • Is not really an erasing type provider, doesn’t scale • Fully erasing type provider, can scale to massive schemas • Is closed source • Completely open source! • Has very limited extensibility points • Pluggable back end, and open source. Go WILD! • Supports a limited set of LINQ functions (currently) • Constraint navigation and querying, “dot individuals” • Supports almost all LINQ functions • Limited schema exploration mechanics
  4. 4. SqlProvider Features • Instant access to a variety of database vendors with no code generation step • Lazily evaluated metadata enabling scaling to large schemas • LINQ queries, presently with the following supported keywords : – select, select many(for), join, distinct, where, take (top), exactlyOne (single), sortBy, sortByDescending, thenBy, thenByDescending • “Dot Individuals” allowing you to directly view the rows of the database as static types via intelliense • Schema navigation – you can directly enumerate over the constraints of an entity – no need to understand the relational design of the database up front to perform joins • Custom operators suc as in In |=| and Like =% • F# Option types can be used for nullable columns • Stored procedures (well, sort of, support for this isn’t great yet!) • Currently support for MS SQL Server SQLite, Postgresql • Debugging hooks
  5. 5. Compile Time Schema Metadata Provided Types Execution Time ISqlProvider Quotations Type Provider LINQ SQL Entity DataContext
  6. 6. Entity Attributes (Columns) Schema Metadata Provided Types Employee Id, Name, etc Company Id, Address, etc Erased Type SqlEntity KeyValue Pairs Order Id, Amount, etc
  7. 7. Entity Relationships (Constraints) Schema Metadata Provided Types Employee { FK Company –> Employee } Company { FK Company –> Employee } { FK Company -> Order } Constraint information Static DataContext Order {FK Company -> Order }
  8. 8. Am I a compiler? Yes. Pretty much. RUNTIME Project Results LINQ AST Execute Query SQL AST Generate SQL SQL Query Type Optimise ISqlProvider LINQ Expression
  9. 9. LINQ Expression Trees!
  10. 10. Nested Active Patterns! | MethodCall(None, (MethodWithName "Join"), [createRelated Convert(MethodCall(_, (MethodWithName "_CreateEntities"), [String destEntity] )) OptionalQuote (Lambda([ParamName sourceAlias],SqlColumnGet(sourceTi,sourceKey,_))) OptionalQuote (Lambda([ParamName destAlias],SqlColumnGet(destTi,destKey,_))) OptionalQuote (Lambda(projectionParams,_))]) -> | OptionalOuterJoin(outerJoin, MethodCall(None,(MethodWithName "_CreateRelated"), [param; _; String PE; String PK; String FE; String FK; String IE; RelDirection dir;])) -> | MethodCall(Some(ParamName name | PropertyGet(_,PropName name)), (MethodWithName "GetColumn"),[String key]) ->
  11. 11. Projection Analysis and transformation steps are applied to the LINQ projection expression; 1) To extract fields that have been explicitly been selected so they can be used to construct a sensible query where possible 2) Entity access nodes are replaced with calls to GetSubEntity() which performs the magic allowing it to seem as if using an ORM, when in reality each row’s data is stored in one master SqlEntity SqlEntity A SqlEntity C GetSubEntity(a) DataRow (SqlEntity) SqlEntity B GetSubEntity(b) GetSubEntity(c) a.Name b.Addr1 b.Addr2 a.Title c.Id c.Amount a.Phone b.Addr2
  12. 12. Extensibility via ADO.NET All you need to do is implement most of this interface! WHAT COULD BE SIMPLER!  type internal ISqlProvider = abstract CreateConnection : string -> IDbConnection abstract CreateCommand : IDbConnection * string -> IDbCommand abstract CreateCommandParameter : string * obj * SqlDbType option -> IDataParameter abstract CreateTypeMappings : IDbConnection -> Unit abstract ClrToEnum : (string -> SqlDbType option) with get abstract SqlToEnum : (string -> SqlDbType option) with get abstract SqlToClr : (string -> Type option) with get abstract GetTables : IDbConnection -> Table list abstract GetColumns : IDbConnection * Table -> Column list abstract GetPrimaryKey : Table -> string option abstract GetRelationships : IDbConnection * Table -> (Relationship list * Relationship list) abstract GetSprocs : IDbConnection -> Sproc list abstract GenerateQueryText : SqlQuery * string * Table * Dictionary<string,ResizeArray<string>> -> string * ResizeArray<IDataParameter> ^ Of course, this last one is the kicker… but thankfully you can largely just copy and paste from an existing provider 
  13. 13. Questions ¿