Julien,
I've recreated everything on one of my servers here and confirm that the error does occur.
Here's what I know so far (discovered using Reflector):
- If a SqlAggregate is constructed in C#, it inherits from System.ValueType. F# by default inherits from System.Object.
- A C# SqlAggregate produces a class with the following IL declaration ".class public sequential ansi serializable sealed beforefieldinit".
- An F# SqlAggregate produces a class with the following IL declaration ".class auto ansi serializable nested public beforefieldinit".
- There are other slight differences in the IL that may/may not be pertinent.
For reference, I created the following C# and F# code to compare. The C# is the standard SQLCLR Aggregate wizard constructed code. I've also included the IL as captured by Reflector. Note that I left the methods collapsed, i.e. the IL within each method has been suppressed as the IL is verbose and method bodies are likely not a cause.
C#----------------------------------------------------
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
using System; using System.Data; using System.Data.SqlClient; using System.Data.SqlTypes; using Microsoft.SqlServer.Server; [Serializable] [Microsoft.SqlServer.Server.SqlUserDefinedAggregate(Format.Native)] public struct Aggregate1 { public void Init() { // Put your code here } public void Accumulate(SqlString Value) { // Put your code here } public void Merge(Aggregate1 Group) { // Put your code here } public SqlString Terminate() { // Put your code here return new SqlString(""); } // This is a place-holder member field private int var1; }
F#----------------------------------------------------
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
module fsqlj #light open Microsoft.SqlServer.Server open System open System.Data.SqlClient open System.Data.SqlTypes [<Serializable>] [<SqlUserDefinedAggregate(Format.Native)>] type dummyAgg = class inherit System.ValueType val mutable value : string new () = {value="a"} member x.Init() = x.value <- "a" member x.Accumulate(v: SqlString) = x.value <- "b" member x.Merge(other : dummyAgg) = x.value <- "c" member x.Terminate () = new System.Data.SqlTypes.SqlString("pop") (* interface Microsoft.SqlServer.Server.IBinarySerialize with end*) end
C# IL----------------------------------------------------
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
.class public sequential ansi serializable sealed beforefieldinit Aggregate1 extends [mscorlib]System.ValueType { .custom instance void [System.Data]Microsoft.SqlServer.Server.SqlUserDefinedAggregateAttribute::.ctor(valuetype [System.Data]Microsoft.SqlServer.Server.Format) = { int32(1) } .method public hidebysig instance void Accumulate(valuetype [System.Data]System.Data.SqlTypes.SqlString 'Value') cil managed { } .method public hidebysig instance void Init() cil managed { } .method public hidebysig instance void Merge(valuetype Aggregate1 Group) cil managed { } .method public hidebysig instance valuetype [System.Data]System.Data.SqlTypes.SqlString Terminate() cil managed { } .field private int32 var1 }
F# IL----------------------------------------------------
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
.class auto ansi serializable nested public beforefieldinit dummyAgg extends [mscorlib]System.ValueType { .custom instance void [System.Data]Microsoft.SqlServer.Server.SqlUserDefinedAggregateAttribute::.ctor(valuetype [System.Data]Microsoft.SqlServer.Server.Format) = { int32(1) } .custom instance void Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype Microsoft.FSharp.Core.SourceLevelConstruct) = { int32(3) } .method public specialname rtspecialname instance void .ctor() cil managed { } .method public instance void Accumulate(valuetype [System.Data]System.Data.SqlTypes.SqlString v) cil managed { } .method public instance void Init() cil managed { } .method public instance void Merge(valuetype fsqlj/dummyAgg other) cil managed { } .method public instance valuetype [System.Data]System.Data.SqlTypes.SqlString Terminate() cil managed { } .property instance string value { .get instance string fsqlj/dummyAgg::get_value() .set instance void fsqlj/dummyAgg::set_value(string) .custom instance void Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype Microsoft.FSharp.Core.SourceLevelConstruct, int32) = { int32(4) int32(0) } } .field public string _value }
I'll do a bit more digging in the next day or so.
Regards,
---O
Could just be a naming problem. Class in F# within a module are created as inner classes in the class that represents the module. In CLR talk an inner class is seperated from it's parent via a + and not a . Which means you might want to try something like:
EXTERNAL NAME [toy_functions].[My_udf+dummyAgg]
The easiest way to check the exact CLR name of dummyAgg is using reflector ([link:www.aisto.com])
And you can also stop dummyAgg being defined as an inner class by adding a namespace declarion to the top of your my_udf.fs file:
1
namespace my_udf
Hi ,
I tried the "+" notation, but it didn't work unfortunately.
And the explicit naming (adding a namespace + module name) didn't make it either.
I also quickly tried to replace the class by a struct (there are examples do that in SQL Server 2005 and c# code, see [link:blogs.msdn.com] )
1 2 3 4 5 6 7 8 9 10 11 12 13 14
[<Serializable;SqlUserDefinedAggregate(Format.Native)>] type dummyAggStruct = struct val mutable value : string new(v:string) = {value=v} member x.Init() = x.value <- "a" member x.Accumulate(v: SqlString) = x.value <- "b" member x.Merge(other : dummyAgg) = x.value <- "c" member x.Terminate () = new System.Data.SqlTypes.SqlString("pop") end
But I can't make be seen either...
By the way, is it possible to use mutable values in a struct ?
I must do something dumb, but with the previous struct, "value" seems immutable
If you :
1 2 3
let test =new dummyAggStruct("myValue") test.Init(); test.value is still "myValue", and not "a"
( Sorry, I didn't want a side-effet in the thread ;) )
Julien
I hoped to reply to this sooner, but I couldn't get to a working SQL installation until today. I had run into similar issues when I tried to complete my ancient blog entries, but I got sidetracked on figuring out how to load the f# library as a safe assembly and then lost my notes :-(
The root problem for the CREATE AGGREGATE error is due to the class being defined as an inner class when in an F# module. As Robert pointed out, this can be fixed by using a namespace. Note that you can't define "standalone" functions in that scope; you'll have to have them in a separate module. CLR UDTs in SQL have the same limitation.
There are some further changes necessary to make your initial example work. The first is to add a System.Runtime.InteropServices.StructLayout attribute with LayoutKind.Sequential. This allows native serialization to work "as expected". The second is limitation of the native serialization to only work with value types; in particular, not strings. You can either work with value types or implement the IBinarySerialize interface as described in [link:msdn2.microsoft.com]. The example is for a UDT so you don't have implement the rest of the UDT-specific functions, just Read() and Write(). The pickler combinators (see [link:www.strangelights.com]) should make this pretty easy. There might be a way using XML serialization, but I can't imagine that it would perform very well.
Let us know how it works.
Lewis
Hi and thanks for your help !
The solution was :
a namespace without module (which means : you cannot mix SqlProcedure or SqlFunction in the same file as your used defined aggregates, as functions are not allowed outside of a module.)
Indeed there were this System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential) attribute to add
So the code (which is a used-defined product) is :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
#light namespace Stuff open System open System.Data open System.Data.Sql open System.Data.SqlTypes open Microsoft.SqlServer.Server open System.Runtime.InteropServices open System.IO [<Serializable;SqlUserDefinedAggregate(Format.Native);System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)>] type MyProd = class val mutable accum : float member x.Init() = x.accum<- 1.0 member x.Accumulate( v: float) = x.accum <- x.accum * v member x.Merge(other : MyProd) = x.accum <- x.accum * other.accum member x.Terminate () = new System.Data.SqlTypes.SqlDouble(x.accum) end
Then the SQL Code is :
1 2 3 4
create assembly other from 'D:\usr\f#\other.dll' with permission_set = unsafe go CREATE AGGREGATE myproduct (@input FLOAT) RETURNS FLOAT EXTERNAL NAME [other].[Stuff.MyProd]
In the future I'll try an example with a user-defined serializer.
Thanks again for your help
Regards
Julien
Topic tags
- f# × 3705
- websharper × 1897
- compiler × 286
- functional × 201
- ui next × 139
- c# × 121
- classes × 97
- web × 97
- .net × 84
- book × 84
- async × 76
- ui.next × 67
- bug × 54
- core × 49
- website × 49
- server × 45
- parallel × 43
- ui × 43
- enhancement × 41
- parsing × 41
- testing × 41
- trywebsharper × 41
- typescript × 37
- html × 35
- javascript × 35
- owin × 35
- asynchronous × 30
- monad × 28
- ocaml × 28
- tutorial × 27
- warp × 27
- haskell × 26
- sitelet × 25
- linq × 22
- workflows × 22
- wpf × 20
- fpish × 19
- introduction × 19
- silverlight × 19
- sitelets × 19
- monodevelop × 17
- rpc × 17
- suave × 17
- piglets × 16
- collections × 15
- feature request × 15
- jquery × 15
- templates × 15
- getting started × 14
- pipeline × 14
- kendoui × 13
- reactive × 12
- 4.1.0.171 × 11
- monads × 11
- opinion × 10
- 4.0.190.100-rc × 9
- deployment × 9
- fixed × 9
- formlets × 9
- in × 9
- json × 9
- plugin × 9
- proposal × 9
- scheme × 9
- solid × 9
- basics × 8
- concurrent × 8
- highcharts × 8
- how-to × 8
- python × 8
- 4.1.1.175 × 7
- complexity × 7
- documentation × 7
- visual studio × 7
- 4.1.2.178 × 6
- lisp × 6
- real-world × 6
- released in 4.0.192.103-rc × 6
- remoting × 6
- resources × 6
- scala × 6
- websharper ui.next × 6
- workshop × 6
- xaml × 6
- 4.0.193.110 × 5
- 4.2.3.236 × 5
- aspnetmvc × 5
- authentication × 5
- azure × 5
- bootstrap × 5
- conference × 5
- dsl × 5
- formlet × 5
- java × 5
- list × 5
- metaprogramming × 5
- ml × 5
- released in Zafir.4.0.188.91-beta10 × 5
- sql × 5
- visualstudio × 5
- websharper.forms × 5
- zafir × 5
- 4.0.192.106 × 4
- 4.0.195.127 × 4
- 4.1.0.38 × 4
- 4.2.1.86 × 4
- 4.2.6.118 × 4
- css × 4
- example × 4
- extensions × 4
- fsi × 4
- fsx × 4
- html5 × 4
- jqueryui × 4
- lift × 4
- reflection × 4
- remote × 4
- rest × 4
- spa × 4
- teaching × 4
- template × 4
- websocket × 4
- wontfix × 4
- 4.0.196.147 × 3
- 4.1.0.34 × 3
- 4.1.6.207 × 3
- 4.2.1.223-beta × 3
- 4.2.11.258 × 3
- 4.2.4.114 × 3
- 4.2.4.247 × 3
- 4.2.5.115 × 3
- 4.2.6.253 × 3
- 4.2.9.256 × 3
- ajax × 3
- alt.net × 3
- aml × 3
- asp.net mvc × 3
- canvas × 3
- cloudsharper × 3
- compilation × 3
- database × 3
- erlang × 3
- events × 3
- extension × 3
- file upload × 3
- forums × 3
- inline × 3
- issue × 3
- kendo × 3
- macro × 3
- mono × 3
- msbuild × 3
- mvc × 3
- pattern × 3
- piglet × 3
- released in Zafir.4.0.187.90-beta10 × 3
- svg × 3
- type provider × 3
- view × 3
- 4.1.1.64 × 2
- 4.1.5.203 × 2
- 4.1.7.232 × 2
- 4.2.10.257 × 2
- 4.2.3.111 × 2
- 4.2.5.249 × 2
- android × 2
- asp.net × 2
- beginner × 2
- blog × 2
- chart × 2
- client × 2
- client server app × 2
- clojure × 2
- computation expressions × 2
- constructor × 2
- corporate × 2
- courses × 2
- cufp × 2
- d3 × 2
- debugging × 2
- direct × 2
- discriminated union × 2
- docs × 2
- elm × 2
- endpoint × 2
- endpoints × 2
- enterprise × 2
- entity framework × 2
- event × 2
- f# interactive × 2
- fable × 2
- flowlet × 2
- formdata × 2
- forms × 2
- fsc × 2
- google maps × 2
- hosting × 2
- http × 2
- https × 2
- iis 8.0 × 2
- install × 2
- interactive × 2
- interface × 2
- iphone × 2
- iteratee × 2
- jobs × 2
- jquery mobile × 2
- keynote × 2
- lens × 2
- lenses × 2
- linux × 2
- listmodel × 2
- mac × 2
- numeric × 2
- oauth × 2
- obfuscation × 2
- offline × 2
- oop × 2
- osx × 2
- packaging × 2
- pattern matching × 2
- performance × 2
- pipelines × 2
- q&a × 2
- quotation × 2
- reference × 2
- released in Zafir.4.0.185.88-beta10 × 2
- rx × 2
- script × 2
- security × 2
- self host × 2
- seq × 2
- sockets × 2
- stm × 2
- tcp × 2
- trie × 2
- tutorials × 2
- type × 2
- url × 2
- var × 2
- websharper.charting × 2
- websharper4 × 2
- websockets × 2
- wig × 2
- xna × 2
- zh × 2
- .net interop × 1
- 2012 × 1
- 4.0.194.126 × 1
- 4.1.3.184 × 1
- 4.1.4.189 × 1
- 4.2.0.214-beta × 1
- 4.2.12.259 × 1
- 4.2.2.231-beta × 1
- 4.2.8.255 × 1
- Canvas Sample Example × 1
- DynamicStyle Animated Style × 1
- Fixed in 4.0.190.100-rc × 1
- Released in Zafir.UI.Next.4.0.169.79-beta10 × 1
- SvgDynamicAttribute × 1
- WebComponent × 1
- abstract class × 1
- accumulator × 1
- active pattern × 1
- actor × 1
- addin × 1
- agents × 1
- aggregation × 1
- agile × 1
- alter session × 1
- animation × 1
- anonymous object × 1
- apache × 1
- api × 1
- appcelerator × 1
- architecture × 1
- array × 1
- arrays × 1
- asp.net 4.5 × 1
- asp.net core × 1
- asp.net integration × 1
- asp.net mvc 4 × 1
- asp.net web api × 1
- aspnet × 1
- ast × 1
- attributes × 1
- authorization × 1
- b-tree × 1
- back button × 1
- badimageformatexception × 1
- bash script × 1
- batching × 1
- binding-vars × 1
- bistro × 1
- body × 1
- bundle × 1
- camtasia studio × 1
- cas protocol × 1
- charts × 1
- clarity × 1
- class × 1
- cli × 1
- clipboard × 1
- clojurescript × 1
- closures × 1
- cloud × 1
- cms × 1
- coding diacritics × 1
- color highlighting × 1
- color zones × 1
- combinator × 1
- combinators × 1
- compile × 1
- compile code on server × 1
- config × 1
- confirm × 1
- content × 1
- context × 1
- context.usersession × 1
- continuation-passing style × 1
- coords × 1
- cordova × 1
- cors × 1
- coursera × 1
- cross-domain × 1
- csla × 1
- current_schema × 1
- custom content × 1
- data × 1
- data grid × 1
- datetime × 1
- debug × 1
- declarative × 1
- delete × 1
- devexpress × 1
- dhtmlx × 1
- dictionary × 1
- directattribute × 1
- disqus × 1
- distance × 1
- do binding × 1
- doc elt ui.next upgrade × 1
- docker × 1
- dojo × 1
- dol × 1
- dom × 1
- domain × 1
- du × 1
- duf-101 × 1
- dynamic × 1
- eastern language × 1
- eclipse × 1
- edsl × 1
- em algorithm × 1
- emacs × 1
- emotion × 1
- enums × 1
- error × 1
- etw × 1
- euclidean × 1
- eventhandlerlist × 1
- examples × 1
- ext js × 1
- extension methods × 1
- extra × 1
- facet pattern × 1
- failed to translate × 1
- fake × 1
- fantomas × 1
- fear × 1
- float × 1
- form × 1
- form-data × 1
- forum × 1
- fp × 1
- frank × 1
- fsdoc × 1
- fsharp × 1
- fsharp.core × 1
- fsharp.powerpack × 1
- fsharpx × 1
- fsunit × 1
- function × 1
- functional style × 1
- game × 1
- games × 1
- gc × 1
- generic × 1
- geometry × 1
- getlastwin32error × 1
- getting-started × 1
- google × 1
- google.maps × 1
- grid × 1
- group × 1
- guide × 1
- hash × 1
- headers × 1
- hello world example × 1
- heroku × 1
- highchart × 1
- history × 1
- how to × 1
- html-templating × 1
- http405 × 1
- httpcontext × 1
- hubfs × 1
- i18n × 1
- ie 8 × 1
- if-doc × 1
- iis × 1
- image × 1
- images × 1
- inheritance × 1
- initialize × 1
- input × 1
- install "visual studio" × 1
- installer × 1
- int64 × 1
- interfaces × 1
- internet explorer × 1
- interop × 1
- interpreter × 1
- io × 1
- iobservable × 1
- ios × 1
- iot × 1
- ipad × 1
- isomorphic × 1
- javascript optimization × 1
- javascript semanticui resources × 1
- jquery-plugin × 1
- jquery-ui × 1
- jquery-ui-datepicker × 1
- js × 1
- kendo datasource × 1
- kendochart × 1
- kendoui compiler × 1
- knockout × 1
- l10n × 1
- learning × 1
- library × 1
- libs × 1
- license × 1
- licensing × 1
- lineserieszonescfg × 1
- local setting × 1
- localization × 1
- logging × 1
- loop × 1
- macros × 1
- mailboxprocessor × 1
- mapping × 1
- maps × 1
- markerclusterer × 1
- markup × 1
- marshal × 1
- math × 1
- mathjax × 1
- message × 1
- message passing × 1
- message-passing × 1
- meta × 1
- metro style × 1
- micro orm × 1
- minimum-requirements × 1
- mix × 1
- mobile installation × 1
- mod_mono × 1
- modal × 1
- module × 1
- mouseevent × 1
- mouseposition × 1
- multidimensional × 1
- multiline × 1
- multithreading × 1
- mysql × 1
- mysqlclient × 1
- nancy × 1
- native × 1
- nested × 1
- nested loops × 1
- node × 1
- nunit × 1
- object relation mapper × 1
- object-oriented × 1
- om × 1
- onboarding × 1
- onclick × 1
- optimization × 1
- option × 1
- orm × 1
- os x × 1
- output-path × 1
- override × 1
- paper × 1
- parameter × 1
- persistence × 1
- persistent data structure × 1
- phonegap × 1
- pola × 1
- post × 1
- powerpack × 1
- prefix tree × 1
- principle of least authority × 1
- privacy × 1
- private × 1
- profile × 1
- programming × 1
- project × 1
- project euler × 1
- projekt_feladat × 1
- protected × 1
- provider × 1
- proxy × 1
- ptvs × 1
- public × 1
- pure f# × 1
- purescript × 1
- qna × 1
- quant × 1
- query sitelet × 1
- question × 1
- quotations × 1
- range × 1
- raphael × 1
- razor × 1
- rc × 1
- reactjs × 1
- real-time × 1
- ref × 1
- region × 1
- released in 4.0.190.100-rc × 1
- reporting × 1
- responsive design × 1
- rest api × 1
- rest sitelet × 1
- restful × 1
- round table × 1
- router × 1
- routing × 1
- rpc reverseproxy × 1
- runtime × 1
- sales × 1
- sample × 1
- sampleapp × 1
- scriptcs × 1
- scripting × 1
- search × 1
- self hosted × 1
- semanticui × 1
- sequence × 1
- serialisation × 1
- service × 1
- session-state × 1
- sharepoint × 1
- signals × 1
- sitelet website × 1
- sitelet.protect × 1
- sitlets × 1
- slickgrid × 1
- source code × 1
- sqlentityconnection × 1
- ssl × 1
- standards × 1
- static content × 1
- stickynotes × 1
- streamreader × 1
- stress × 1
- strong name × 1
- structures × 1
- submitbutton × 1
- subscribe × 1
- svg example html5 websharper.ui.next × 1
- sweetalert × 1
- system.datetime × 1
- system.reflection.targetinvocationexception × 1
- table storage × 1
- targets × 1
- tdd × 1
- templates ui.next × 1
- templating × 1
- text parsing × 1
- three.js × 1
- time travel × 1
- tls × 1
- tooltip × 1
- tracing × 1
- tsunamiide × 1
- turkish × 1
- twitter-bootstrap × 1
- type erasure × 1
- type inference × 1
- type providers × 1
- type-providers × 1
- typeprovider × 1
- ui next forms × 1
- ui-next × 1
- ui.next jqueryui × 1
- ui.next charting × 1
- ui.next formlets × 1
- ui.next forms × 1
- ui.next suave visualstudio × 1
- ui.next templating × 1
- unicode × 1
- unittest client × 1
- upload × 1
- usersession × 1
- validation × 1
- vb × 1
- vb.net × 1
- vector × 1
- view.map × 1
- visal studio × 1
- visual f# × 1
- visual studio 11 × 1
- visual studio 2012 × 1
- visual studio shell × 1
- vs2017 compiler zafir × 1
- vsix × 1
- web api × 1
- web-scraping × 1
- webapi × 1
- webcomponents × 1
- webforms × 1
- webgl × 1
- webrtc × 1
- webshaper × 1
- websharper async × 1
- websharper codemirror × 1
- websharper f# google × 1
- websharper forms × 1
- websharper reactive × 1
- websharper rpc × 1
- websharper sitelets routing × 1
- websharper warp × 1
- websharper-interface-generator × 1
- websharper.chartsjs × 1
- websharper.com × 1
- websharper.exe × 1
- websharper.owin × 1
- websharper.ui.next × 1
- websharper.ui.next jquery × 1
- websockets iis × 1
- why-websharper × 1
- windows 7 × 1
- windows 8 × 1
- windows-phone × 1
- winrt × 1
- www.grabbitmedia.com × 1
- xamarin × 1
- xml × 1
- yeoman × 1
- yield × 1
- zafir beta × 1
- zafir websharper4 × 1
- zarovizsga × 1
![]() |
Copyright (c) 2011-2012 IntelliFactory. All rights reserved. Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy |
Built with WebSharper |
Hi,
I'm playing with Sql Server and F#
I know there has been a post on this topic some time ago, but just to sum up, here is how to define SqlProcedures and SqlFunctions
If you compile this into a file named my_udf.fs, without mentioning a module name,
the code is referenced as if you created a "My_udf" module (note the uppercase).
Run a compilation as a dll (fsc -a my_udf.fs)
Then you run the following code in Sql Server:
So far so good.
Now User Defined Aggregate. It's a cool feature, say to run statistical functions (Gini coefficient, median, inter-quartile range, whatever)
Here's a dummy function for it :
The problem :
I cannot reference the type : it's not seen by Sql Server
When trying to reference it :
it throws a
Msg 6556, Level 16, State 1, Line 1
Échec de 'CREATE AGGREGATE', le type 'My_udf.dummyAgg' étant introuvable dans l'assembly ''toy_functions'.
Msg 6597, Level 16, State 2, Line 1
CREATE AGGREGATE a échoué.
Which means : cannot find your type dummyAgg
I think I exhausted all the combinaisons in the name (the part after EXTERNAL NAME), but the problem seems elsewhere.
Do you have any ideas?
Many thanks in advance
Regards,
Julien