Can NHibernate QueryOver have a SQL-where statement? - nhibernate

I'm new to Nhibernate. My problem is that I want to narrow down a query by using a column that is not included in my entity (ie hbm). I want to do something like this:
Session.QueryOver<MyEntity>()
.SQL_Where("MyFlag = 1")
Since I have no use of that flag later I don't want to include it to the entity
I know I can use:
Session
.CreateSQLQuery("SELECT A,B,C FROM ENTITY WHERE MyFlag = 1")
.SetResultTransformer(Transformers.AliasToBean<MyEntity>())
.List<MyEntity>();
It would be nice to use QueryOver<>(), it's more safe if a column is added etc.

You may be able to use filters:-
Put a filter on your mappings class definition, however this will affect ALL returned rows
e.g.
<class name="Domain.Model.MyEntity, Domain.Model" table="MyTable"
where="(MyFlag=1)">
...
</class>
or it may be possible to use conditional filters with QueryOver
<filter-def name="SetMyFlag">
<filter-param name=":flag" type="System.Int"/>
</filter-def>
<class name="Domain.Model.MyEntity, Domain.Model" table="MyTable">
...
<filter name="SetMyFlag" condition="(MyFlag=:flag)"/>
</class>
and use:-
session.EnableFilter("SetMyFlag").SetParameter("flag", 1);
session.QueryOver<MyEntity>();
Although I have never use conditional filters with unmapped columns so this may not work!

Related

Mapping inherited class with nhibernate hbm

I Have 2 classes of the same table.
one class, "Entity", contains properties x,y,z from table ENTITY
and the derived class, "ExtendedEntity" contains some more properties (collections - relations to other tables).
I want to map both of them but i couldn't find a way to map subclasses without using discriminator (I dont need one, sometimes i want to select the Entity object and sometimes the ExtendedEntity).
does anyone has any idea?
(I tried to map the ExtendedEntity by copying the Entity mapping and adding the new properties, but now when i want to get the Entity object it brings me ExtendedEntity).
Thanks!
Taking into account the first sentence of your question:
I Have 2 classes of the same table.
It means that there is only one table ("ENTITY"). If this is true, there do not have to be, and even should not be any inheritance, if no discriminator exists. If both entities will be related to all rows, then (instead of inheritance) we need laziness. And only one Entity profiting from the native NHibernate behavior: having lazy properties. And even more, to optimize some queries - the Projections could be used.
But again, my suggestion could be correct only if I do understand your scenario correctly: the two entities were introduced only to reduce workload; but both target all rows in one table.
The mapping for the only class
<class name="Entity" table="ENTITY" lazy="true">
<id name="ID" column="Entityd">
<generator class="native"></generator>
</id>
<!-- standard default always loaded properties -->
<property name="Code" />
<property name="Name" />
<!-- only if accessed, lazily loaded properties -->
<many-to-one lazy="proxy" name="Currency" column="CurrencyId" cascade="none" />
<property lazy="true" name="Image" column="ImageBinary" />
...
Having this mapping we can get first 5 Entities
var list = session.CreateCriteria<Entity>()
.SetMaxResults(5)
.List<Entity>();
And SQL statement generated will be:
SELECT TOP 5 this_.EntityId as EntityId3_1_
, this_.Code as Code3_1_
, this_.Name as Name3_1_
FROM ENTITY this_
And we can even reduce it with projections
var propertyList = NHibernate.Criterion.Projections.ProjectionList();
// projection properties
propertyList.Add(NHibernate.Criterion.Projections.Property("ID"));
propertyList.Add(NHibernate.Criterion.Projections.Property("Code"));
var projected = session.CreateCriteria<Entity>()
.SetMaxResults(5)
.SetProjection(propertyList)
.SetResultTransformer(new NHibernate.Transform
.AliasToBeanResultTransformer(typeof(Entity)))
.List<Entity>();
In this case is the SQL Select even smaller. If the ID and Code would be enough..
SELECT TOP 5 this_.Code as y0_
, this_.EntityId as y1_
FROM ENTITY this_
So, in case I read your question correctly, in your scenario solution would not be in inheritance but in NHibernate native laziness
NOTE: there could be ExtendedEntity derived from Entity even in this scenario. But not for inheritance via NHibernate mapping but for the Projections Transformation. Some properties from many-to-one properties could be projected this way...

Querying by property of mapped subclass in NHibernate

I'm very new to NHibernate so this may be fairly trivial, but searching is leaving me confused.
I have an AddOnAmount table as follows:
AddOnID | AddOnTypeID | Period | Amount
where AddOnTypeID is a FK. The rows have a unique constraint on AddOnTypeID and Period.
The mapping looks like this:
<id name="Id" column="AddOnId" type="long">
<generator class="native" />
</id>
<many-to-one name="AddOnType" column="AddOnTypeID" class="AddOnTypeStatic" not-null="true" />
<property name="Period" />
etc.
The AddOnTypeStatic class/table just has an Id, which is the numerical value stored on the table, and a descriptive Name.
I'm trying to write a query that will search by AddOnTypeId and Period, so I can validate the existence (or not) of a row before attempting to add a duplicate from my front end, but I'm not sure how to do that as the AddOnAmountStatic class has a subclass whereas the table has just an Id.
So far I've written:
public AddOnAmountStatic FindByAddOnTypeAndPeriod(long addOnType, string period)
{
return FindOne(CreateCriteria()
.Add(Restrictions.Eq("AddOnTypeId", addOnType))
.Add(Restrictions.Eq("Period", period))
.SetCacheable(true));
}
which does not work, as AddOnTypeId isn't a property of AddOnAmountStatic. Not sure how to access the property of the subclass in this context.
My mapping works, as I've been using it so far with no problems.
Solved my problem - it was simple but thought I'd add the solution here in case it helps anyone else.
I'd been thinking of constructing the query from the table's perspective (i.e., with the AddOnTypeID), whereas what I should have done is look at it from the entity's perspective. In other words, I just needed to pass in an AddOnTypeStatic object.
What I did was take my AddOnTypeID parameter, check it exists through NHibernate (returning either an AddOnTypeStatic object or null) then passed that through to the original query. Final query is simply
return FindOne(CreateCriteria()
.Add(Restrictions.Eq("AddOnType", addOnType))
.(Restrictions.Eq("Period", period))
.SetCacheable(true));
Hope this helps another newbie!

NHibernate query against the key field of a dictionary (map)

I have an object model where a Calendar object has an IDictionary<MembershipUser, Perms> called UserPermissions, where MembershipUser is an object, and Perms is a simple enumeration. This is in the mapping file for Calendar as
<map name="UserPermissions" table="CalendarUserPermissions" lazy="true" cascade="all">
<key column="CalendarID"/>
<index-many-to-many class="MembershipUser" column="UserGUID" />
<element column="Permissions" type="CalendarPermission" not-null="true" />
</map>
Now I want to execute a query to find all calendars for which a given user has some permission defined. The permission is irrelevant; I just want a list of the calendars where a given user is present as a key in the UserPermissions dictionary. I have the username property, not a MembershipUser object. How do I build that using QBC (or HQL)? Here's what I've tried:
ISession session = SessionManager.CurrentSession;
ICriteria calCrit = session.CreateCriteria<Calendar>();
ICriteria userCrit = calCrit.CreateCriteria("UserPermissions.indices");
userCrit.Add(Expression.Eq("Username", username));
return calCrit.List<Calendar>();
This constructed invalid SQL -- the WHERE clause contained WHERE membership1_.Username = #p0 as expected, but the FROM clause didn't include the MemberhipUsers table.
Also, I really had to struggle to learn about the .indices notation. I found it by digging through the NHibernate source code, and saw that there's also .elements and some other dotted notations. Where's a reference to the allowed syntax of an association path? I feel like what's above is very close, and just missing something simple.
Just trying to do this myself and it looks like this can be done with HQL but not the Criteria API.
https://nhibernate.jira.com/browse/NH-1795
To do it in HQL:
http://ayende.com/Blog/archive/2009/06/03/nhibernate-mapping-ndash-ltmapgt.aspx
Specifically look for Ayende's comment:
It is something like:
select 1 from Profile p join p.Entries e
where index(e) = 'HasCats' and e = 'true'

Eagerly load recursive relation

I have a recursive one-to-many relationship that has the default lazy value of true. What code can I write against the NH API that will efficiently retrieve the ENTIRE tree AS IF I had lazy="false" on the SubCategories mapping?
Here's the recursive one-to-many relationship:
<class name="Category" lazy="false">
...
<list name="SubCategories" fetch="subselect">
<key column="ParentCategoryID"/>
<index column="PositionInList"/>
<one-to-many class="Category"/>
</list>
I don't specify lazy="false" on the list since laziness is required in about half the queries I need to run. I have fetch="subselect" on the list as an optimization for when I do manage to retrieve the entire tree.
I've tried the ICriteria API:
session.CreateCriteria<Category>().SetFetchMode( "SubCategories", FetchMode.Eager ).Add( Restrictions.IsNull("ParentCategory") ).SetResultTransformer( CriteriaSpecification.DistinctRootEntity ).List<Category>();
but that only eagerly loaded only the first level in the hierarchy.
See Ayende's site: Efficiently Selecting a Tree. I have successfully used this technique in my own applications. With ICriteria, it looks like this:
session.CreateCriteria<Category>()
.SetFetchMode("SubCategories", FetchMode.Join)
.SetResultTransformer(new DistinctRootEntityResultTransformer())
.List<Category>()
.Where(x => x.ParentCategory == null);
The main difference between this version and what you tried is how the "ParentCategory == null" filter is applied. It has to be left out of the query that is sent to the database in order to retrieve the whole tree - but we still need the query to only return the root nodes of the tree, so we'll use linq to find those after the database query has completed.
I used Daniel's code as a bases for solving the problem. I also experimented with the equivalent HQL that I shared below. The HQL executed slightly faster, but I went with ICriteria since I could then choose between FetchModel.Join and FetchModel.Lazy.
session.CreateQuery( "from Category as c left join fetch c.SubCategories" )
.SetResultTransformer( new DistinctRootEntityResultTransformer() )
.List<Category>()
.Where( c => c.ParentCategory == null );
Not sure if it helps but take a look at : map a tree in NHibernate

Map a property to the latest entry in NHibernate

Let's say my domain looks like this:
I have an object, Vehicle, that has an OdometerReading property.
An OdometerReading has the Miles & Date (when it was read).
I need to keep a history of all OdometerReadings for the Vehicle in the database, but don't want the entire odometer history to belong to the Vehicle object. What I would like is for the OdometerReading property map to the most recent OdometerReading entry out of the database.
I thought about mapping the whole collection of OdometerReadings to the Vehicle, and having a dynamic property called CurrentOdometerReading that would order them and return the latest one, but I don't need the whole collection under the Vehicle in my domain, and it seems like I would be getting more data out of the database than I need.
Is that possible with NHibernate? How would I map such a thing?
There are a few ways of doing this depending on what you want your domain model to look like. My preferred choice is to use a custom collection type, for example IOdometerReadingCollection, which you can add extra methods to. In this case it might be something like:
public interface IOdometerReadingCollection : IList<OdometerReading>
{
OdometerReading Latest { get; }
}
This way you can do:
OdometerReading reading = vehicle.OdometerReadings.Latest;
which I prefer to:
OdometerReading reading = vehicle.LatestOdometerReading;
There's lots of documentation about custom collections, which you can find with a simple google search.
If this approach isn't for you there are other options. You may be able to use a property with a formula (I'm not sure if that works with complex types?), or a regular NHibernate association where you'd have the key of the latest OdometerReading on your Vehicle mapping. As you also mentioned you could just load all the OdometerReadings, which depending on your use case might actually be fine.
I hope this helps, or at least points you in the right direction.
There is a "where" clause that you can put in your collection mapping. Check the reference documentation.
I would map the OdometerReading property as a component, then use a named query to ensure it's populated with the latest reading out of the database. (In this example, you'd have a sql-query with a name of "vehicle" that does the SQL to load the Vehicle columns along with the latest Odometer reading)
<class name="Vehicle">
<property name="Type" not-null="true"/>
<component name="OdometerReading">
<property name="Miles" />
<property name="Date" />
</component>
<loader query-ref="vehicle"/>
</class>