I know this question could lead to a subjective answer, but I'd like to get an opinion from someone else.
Some background
Currently I have a class that maps a private string property to a geometry column in a PostgreSQL (PostGIS) database table along with a public string for WKT. The WKT is used by PostGIS to automatically update the geometry column, using a trigger. As I don't want to include any spatial references in my domain model, all querying is done using WKT strings and a custom spatial criterion, which wraps the WKT in a spatial PostGIS function and queries the private geometry property column reference. All of this works as expected.
The question
Since I need the column reference, I also need the property in my domainmodel, for NHibernate to map to, so I was wondering, what the best solution would be, for NHibernate to never select this property.
My current solution looks as follows with Fluent NHibernate:
Map(Reveal.Member<LocationReference>("Geometry"), "geometry")
.Generated.Always()
.ReadOnly()
.LazyLoad();
This does the trick, and when I select the entity, I won't get the property, unless I manually load it (which isn't possible through the lambda extensions). Unfortunately I would still be able to do a Criteria or HQL query for the property.
So are there any ways for me to do anything that prevents NHibernate from being able to do ever include the column in a select? Or is the above solution the only way to at least ignore the column when selecting with Query<> or QueryOver<>?
Well, I ended up removing the mapped property, because, even though it was lazy, NHibernate would sometimes load it anyway. What I did was actually a bit of a hack. I needed the alias for a property from the same class, so I used the mapping from another property and split the SqlString on '.', to get the correct alias.
All of this makes perfect sense to me, and the "workaround" is not nice, but I don't see any other way of doing it. NHibernate needs to know, what property it's dealing with, to assign proper aliases. Since I'm not mapping the property, it has no way of knowing, what alias I'm looking for.
I guess I'm doing a lot of hacking, just to avoid having to reference NHibernate.Spatial...
Related
Well I know the necessity of tags in struct in golang and how is it accessed by reflect in golang. But I have searched and could not find a reliable answer to the question of why I should use sql tags in struct while writing struct for sql results. I have explored many sample code and people are using sql:"index" in the struct and sql:"primary_key" in the struct.
Now I have done indexing in the database layer, isn’t it enough? Should I have to use sql:"index" too get the best results? Like so I have defined primary key attribute in the database should I have to specify sql:"primary_key" as well?
My code seems to work fine without those. Just want to know their benefit and usages.
I think you are referring to an ORM library like gorm
In that case, metadata like sql:"primary_key" or sql:"index" will just tell the ORM to create an index while trying to setup the tables or maybe migrate them.
A couple of examples in gorm could be: indexes, primary keys, foreign keys, many2many relations or when trying to adapt an exiting schema into your gorm models, setting the type explicitly, like for example:
type Address struct {
ID int
Address1 string `sql:"not null;unique"` // Set field as not nullable and unique
Address2 string `sql:"type:varchar(100);unique"`
Post sql.NullString `sql:"not null"`
}
Depends on the package you are using and your use-case. Is it enough for CRUD? Almost always, unless the package says so which is often rare but possible. Few packages sometime do under the hood magic which may give rise to bugs. If you are aware of these behaviours, or are quite explicit in your code, you'll probably avoid it.
Indexing tags mostly allows you to use package's migration tools translating your model declaration into sql queries (CREATE statements). So if you always want to do this by yourself, then you probably needn't bother adding such tags.
But you may find yourself a bug if your package requires a tag. For example, in case of gorm, the Model method takes a struct pointer as an input. If this struct has a field named ID it uses it as a primary key, that is, say ID has a value of "4", it will add a WHERE id=4 automatically. In case your struct has ID, you needn't even add a primary_key tag and it will still be treated as one. This behaviour may cause issues when you have both a "non-primary-key" ID field, and another field which you are actually using as the primary key. Another example for gorm is this. A possible behaviour can also be checking for nullable property and throwing an error if an INSERT statement involves a NOT NULL field getting a NULL value.
On a different note, adding tags to your structs can be considered good practice since it gives context of its properties in the DB.
I am trying to find a way to only populate a property of my entity class, if the column exists in the query?
When I execute a query using DbSet.SqlQuery and returning the column (which is an alias) populated, everything is fine. But when using the built in functionality such as All(), Find(), ToArray() etc, it expects that column to be in the dataset.
Is there a way (without having to write all of the supporting queries manually) to mark a property in my entity class, as optional.
It is currently marked as a nullable DateTime but the framework still complains it does not exist when using the built in functionality.
Any suggestions would be great!
Cheers
No, because they have to build the SQL query. It doesn't matter if a column is nullable or not, what matters is that when they build the query, if that column does not exist, then the database will likely throw an error complaining that the column does not exist.
The only way around it is to not map it, or to query the schema when mapping and conditionally map the property (though I wouldn't recommend that).
I have a named hql query which makes use of object constructors for an object that is not mapped (it is only imported)
e.g.
select distinct new NotMappedResultClass(ah.SomeProp1, ah.SomeProp2)
from SomeMappedClass
where ...
order by ah.SomeProp1
The weird thing is, that when I call IQuery.List() in NHibernate, I end up with exactly twice as many rows from NHibernate than from the query that NHibernate ran (traced using SqlProfiler).
(In case it matters, the "where" clause does actually involve some subqueries).
Why is NHibernate duplicating the rows coming back from the database?
(I am using NHibernate 1.2.1.4000)
Found the problem.
My project has some odd mappings when it comes to inherited classes.
Basically, SomeMappedClass was abstract, and had its own NHibernate mapping, and there was a derived class SomeDerivedClass (that didn't add any functionality) that was also mapped separately without the "extends" attribute.
This caused NHibernate to issue two sql queries, with different aliases for the same table.
In my case the simple quick and dirty solution was to query from SomeDerivedClass instead of SomeMappedClass, but the more appropriate solution would probably be to modify the mappings / object inheritance.
I have two tables - Run and Sample, where Sample.RunId is a foreign key linking samples to their runs.
I would like to have a SampleCount property in Run, which is the number of Sample objects associated with the particular Run.
Is it possible to map such a property in NHibernate mapping of the Run type?
Thanks.
Although the collection solution by Diego Mijelshon is perfectly valid it does mean an extra query after fetching the Run entity. If you haven't mapped the collection and you do not want to or you do not want the additional query, consider a "computed" property as such
in the Run class mapping
<property name="SamplesCount" type="long" formula="(select count(s.Id) from Samples s where s.RunId = Id)" />
and in the class Run just add
long SamplesCount {get; set;}
Note that in the query, for the part "s.RunId = Id" NHibernate will insert the proper alias for the root table. Also, don't forget the parenthesis, it makes it easier for the parser and in some cases is required.
This approach has the benefit of applying a subquery on the select (which may or may not be good depending on your case). The property can also be lazily-loaded (i think a NH 2++ feature) if this property is something you will only rarely need.
While you can do that using a <join>, it's not a good idea.
Instead, declare your Run.Samples collection as lazy="extra", and accessing Run.Samples.Count will do a query for the count instead of loading the entire collection.
I have a table in database which has some columns like year,name and also 12 columns (m1,m2,...,m12) representing months. I would like to map this table into one class using NHibernate, ideally, these 12 mapped columns would look like:
_mappedMonths[] = new double[12];
Has anyone a solution for this ?
If you really want to map the columns directly to an array, as you describe, take a look at the ICompositeUserType interface. You can find an article about custom NHibernate mapping here, and this blog post might be of interest as well.
However, if it is not super important you might consider mapping the columns just as you normally would, but as private/protected properties, and then create a public property in your class that exposes those private/public properties as an array. That would be a simpler and faster solution, but would result in code that is not quite as clean.