Is it possible to do Standard Deviation in NHibernate? - nhibernate

Is it possible to calculate Standard Deviation with NHibernate? I'm using the Microsoft SQL Server 2005 Dialect.
I can't find any examples of this anywhere.
Please help.
thanks!

Just wanted to let everyone know how I accomplished this with code that may help others:
When I create my SessionFactory, I simply add a custom SQL Function to the Configuration Object:
Setup:
var configuration = new Configuration();
configuration.AddSqlFunction("stdev", new StandardSQLFunction("stdev", HibernateUtil.Double));
SessionFactory = configuration.Configure().BuildSessionFactory();
Usage:
Then in my data provider I now can call the custom function:
ICriteria criteria = _session.CreateCriteria(typeof(ItemHistory));
criteria.SetProjection(Projections.SqlFunction("stdev", NHibernateUtil.Double, Projections.Property("Speed") ));
IList results = criteria.List();

I'm not that familiar with NHibernate, but using the Java Hibernate you can subclass an existing dialect easily to add extra functions. Something like this might do the trick for you (this is the Java version):
public class MyDialect extends SQLServerDialect
{
public MyDialect()
{
super();
// register extra functions (may need to specify parameter types)
registerFunction( "stdev", new StandardSQLFunction( "stdev" ) );
}
}

STDEV is a native SQL function for SQL Server... can you pass through a native query?

You can use native SQL queries, including aggregate functions, in HQL (Hibernate Query Language). See Chapter 12 in the documentation.
Edited to add: I just read it myself and STDEV is not supported. An alternative that might work is to create a view that includes the calculation and map the view instead of the table. Further Googling leads me to believe that the documentation may be out of date or there are extensions to NHibernate that include STDEV.

I've solved in a more standard way by this code:
sqrt((sum(value*value)/count(value)) - (avg(value) * avg(value)))
In other way, unrolling the formula of the standard deviation using the other aggregate functions that are supported: sum and count.
I've checked against the formula 'std()' in mysql and this works except by the least significant digits (error less of 0.000000001D).

Related

PyQt - Use SQL directly with QSqlTableModel

I'm writing a simple student scores manager for practicing programming on PyQt (I don't want to use terrible Visual Basic anymore). But I had a big problem on choose data models.
I found QSqlTableModel first, it is a great model with auto-updating. The trouble is, I need to use a lot of SQL (JOIN, WHERE) to select data from database. QSqlTableModel has select() and filter() only.
Then I found QSqlQueryModel, but it is read only. So I rewrite its setData() method. So it is read-write now. Unfortunately, QSqlQueryModel less usable features than QSqlTableModel.
As you see, if I can using SQL with QSqlTableModel, I can resolve all my problems.
So...?
QSqlTableModel has the setQuery method, which you can use to set a custom query, something like:
model = QSqlTableModel()
query = QSqlQuery(your_query)
model.setQuery(query)
However, the Qt documentation states:
This function simply calls QSqlQueryModel::setQuery(query). You should normally not call it on a QSqlTableModel. Instead, use setTable(), setSort(), setFilter(), etc., to set up the query.

C#'s 'dynamic' in F#

One example of using the DLR in C# is as follows:
dynamic dyn = new MyObject();
dyn.MyMethod(); //resolved at runtime
what would be the equivalent in F#?
Thanks.
The ? operator has similar expressive power to the dynamic keyword in C# (but it can be only used for reading of properties, method invocation and setting of properties).
There is no built-in implementation that would allow you to dynamically use properties or methods of a .NET class (via Reflection or DLR), but there are some fairly solid implementations from the community. This has been discussed in another SO question before.
There are also implementations of ? that allow you access some common data sources such as SQL databases. For example, this MSDN article includes a definition that allows you to write db?Query?Foo(1) to call a stored procedure named Foo.
For various other types (such as finding an element in XAML or accessing elements or attributes in XML document), the definition of ? is quite easy to write.
On the flip side, if you're trying to expose dynamic behavior to C# from F#, you can use DynamicAttribute[MSDN]. For example, declaring a dynamic property might look like
type HasDynamicProperty() =
[<Dynamic([|true|])>]
member this.DynamicObject : obj = ...
which is used from C# like
var hdp = new HasDynamicProperty();
dynamic dynObj = hdp.DynamicObject;
There's a package called FSharp.Interop.Dynamic and that will make it possible to do a call to a dynamic object using the ? operator.
F# has the ? operator which you use like so:
myVariable?SomePropertyThatIsNotDeclared
There is no dynamic keyword equivalent. Take a look at this article for how to use it https://weblogs.asp.net/podwysocki/using-and-abusing-the-f-dynamic-lookup-operator

Fluent NHibernate RegisterFunction SQLFunctionTemplate usage

I've seen this opportunity reported at least half a dozen times with about as many responses.
My problem is, I've got a MySQL database function defined, we'll call it "my_func(int val) returns int", which works fine if I test directly on the database.
I've also gotten it to work with a direct SQL passthrough my repository implementation, which is okay, but I'd rather route it through Hql, for some god-awful reason...
So... I've got a MySQL5Dialect setup to register the function and I'm having some difficulty parsing through the expected conventions.
My understanding is that I need to prefix the function name with "dbo." at some point during the function registration?
Something like this,
//...
RegisterFunction("my_func", new SQLFunctionTemplate(NHibernateUtil.Int32, "my_func(?1)"));
//...
And then through my repository,
var value = repository.FindByHQL<int>("select my_func(2)").Single();
Where FindByHQL returns an IList.
Any thoughts why this wouldn't work.
I'm running the latest WAMP (2.1e I think).
Enough info? Let me know if I can provide any further details.
Thanks,
Michael
select my_func(2)
is not valid HQL, regardless of whether the function is registered or not.
You can use SQL instead if that's your use case.
Post full exception with stack trace if it's not and this was just a simplified example.

NHibernate ISQLQuery SetParameter issue

This is probably fairly straightforward but i can't seem to find a reasonable explanation in any documentation.
I'm trying to use an NHibernate.ISQLQuery and using SetResultTransformer() to return a custom set of results from a custom SQL query. Like so:
public virtual IList<T> GetSQLObject<T>(string sql, IDbParameter[] parameters = null)
{
ISQLQuery qry = _sess.CreateSQLQuery(sql);
qry.SetResultTransformer(Transformers.AliasToBean(typeof(T)));
if (parameters != null) {
foreach (IDbParameter parameter in parameters) {
qry.SetParameter(parameter.Name, parameter.Value);
}
}
return qry.List<T>();
}
From looking at the examples, it seems that in the sql query I have to use parameters in the format :param1 instead of #param1 as I would in a standard SQL query. If i use the latter syntax in the query, it throws an error at qry.SetParameter().
Is there a reason why ISQLQuery/NHibernate requires them in this format and won't work with the normal syntax?
SQL Server uses #param, but not every other database does. For example, MySQL uses ?param
NHibernate allows you to swap out 1 database implementation for another with little to no reworking of your DAL. It sets the parameters based on the database you configured when you setup the NH Configuration.
Edit: Also I think :param came about from Hibernate being targeted at Oracle when it was initially developed, since Oracle uses :param
Phil has answered the "why"; so perhaps I can recommend a "how"; why not just add a new extension method to the IDbParameter type (something like .GetNHibernateName() ) that will return the parameter name with the "#" replaced with a ":"; that should be trivial to implement.

VB.net can't find by string

Using VB.net, the following snippet gives the error below.
Dim _account = Account.Find(Function(x As Account) x.AccountName = txtFilterAccountName.Text)
or similarly if I do
.SingleOrDefault (Function(x As Account) x.AccountName = txtFilterAccountName.Text)
will both give the error "The method 'CompareString' is not supported". If I make the same call searching for an integer (ID field) it works fine.
.SingleOrDefault (Function(x As Account) x.Id = 12)
So integer matching is fine but strings don't work Is this a problem with the VB.net templates?
No this is not a problem with Vb.Net templates.
The problem is that you are not using a normal LINQ provider. Based on your tag (subsonic) I'm guessing you're using a LINQ to SQL query.
The problem is that under the hood, this is trying to turn your code into an expression tree which is then translated into an SQL like query. Your project settings are turning your string comparison into a call in the VB runtime. Specifically, Microsoft.VisualBasic.CompilerServices.Operators.CompareString.
The LINQ2SQL generater in question or VB compiler (can't remember where this check is done off the top of my head) does not understand how to translate this to an equivalent bit of SQL. Hence it generates an error. You need to use a string comparison function which is supported by LINQ2SQL.
EDIT Update
It looks like the CompareString operator should be supported in the Linq2SQL case. Does subsonic have a different provider which does not support this translation?
http://msdn.microsoft.com/en-us/library/bb399342.aspx
The problem is with SubSonic3's SQL generator and the expression tree generated from VB.NET.
VB.NET generates a different expression tree as noted by JaredPar and SubSonic3 doesn't account for it - see Issue 66.
I have implemented the fix as described but it has yet to merge into the main branch of SubSonic3.
BlackMael's fix has been committed:
http://github.com/subsonic/SubSonic-3.0/commit/d25c8a730a9971656e6d3c3d17ce9ca393655f50
The fix solved my issue which was similar to John Granade's above.
Thanks to all involved.