NHibernate join query over multiple databases - nhibernate

I am working on a legacy app and need to query over two tables from two different databases.
Bar the option of selecting both sets of data, then filtering the results are there any other options or best practices for this?
Ideally I would like to run a single query and output the results to a DTO.
Thanks

In your mapping document, specify the table name for the class and prefix it w/ the database name and schema name:
<class name="BvCustomProduct" table="RelaunchCustom.dbo.bvc_Product">
...
</class>
NH should join between the two DBs w/ no problem. This example is for SQL Server, I've not tried it on other dialects but it likely works the same.

Related

Is there a way in JOOQ to pull a number of records without multiple DB calls?

In our webapp we have a number of places where you would be updating a number of tables in one complex form/view. In raw SQL I would probably select a bunch of columns from a bunch of tables and edit that one record on the primary table as well as related parent/child tables.
In hibernate I would probably just pull a JPA entity for the main table and let hibernate fetch the parent/child relationships as I populate the view. And then later pull from my view back to the entity and call entitymanger .perist/merge.
In JOOQ I have a number of options but it appears you can pull a main record via selectFrom/fetch then use fetchChild fetchParent to pull typed related records like so...
LoadsRecord load = dslContext.selectFrom(LOADS)
.where(LOADS.ID.eq(id))
.fetchOne();
SafetyInspectionsRecord safetyInspection = load.fetchParent(Keys.LOADS__FK_SAFETY_INSPECTION);
So this way I am able to pull related records in a typesafe manner. The only annoying thing is I have to run another full query every time I call fetchParent or fetchDhild. Is there a way to eagerly fetch these all at once to avoid multiple round trips to the DB?
It is really nice to have these classes like LoadsRecord for CRUD screens, it makes updating the DB easy.
Classic approach using joins
There are various ways you can achieve materialising a to-one relationship. The simplest one being a simple JOIN or LEFT JOIN if the relationship is optional.
E.g.:
Result<?> result =
ctx.select()
.from(LOADS)
.join(SAFETY_INSPECTIONS)
.on(LOADS.SAFETY_INSPECTIONS_ID.eq(SAFETY_INSPECTIONS.ID))
.fetch();
You probably want to work with the generated records thereafter, so you can use various mapping tools to map the generic Record types to the two UpdatableRecord types for further CRUD:
for (Record r : result) {
LoadsRecord loads = r.into(LOADS);
SafetyInspectionsRecord si = r.into(SAFETY_INSPECTIONS);
}
Using nested records
Starting from jOOQ 3.15 and #11812, MULTISET and ROW operators can be used to create nested collections and records. So, in your query, you could write:
Result<?> result =
ctx.select(
row(LOADS.ID, ...),
row(SAFETY_INSPECTIONS.ID, ...))
.from(LOADS)
.join(SAFETY_INSPECTIONS)
.on(LOADS.SAFETY_INSPECTIONS_ID.eq(SAFETY_INSPECTIONS.ID))
.fetch();
That would already help map the nested data structures into the desired format. Starting from jOOQ 3.17 and #4727, you can even use table expressions directly to generate nested records:
Result<Record2<LoadsRecord, SafetyInspectionsRecord>> result =
ctx.select(LOADS, SAFETY_INSPECTIONS)
.from(LOADS)
.join(SAFETY_INSPECTIONS)
.on(LOADS.SAFETY_INSPECTIONS_ID.eq(SAFETY_INSPECTIONS.ID))
.fetch();
This new feature is definitely going to close one of jOOQ's biggest gaps. You could even simplify the above using implicit joins to this:
Result<Record2<LoadsRecord, SafetyInspectionsRecord>> result =
ctx.select(LOADS, LOADS.safetyInspections())
.from(LOADS)
.fetch();

Automatically connect SQL tables based on keys

Is there a method to automatically join tables that have primary to foreign relationship rather then designate joining on those values?
The out and out answer is "no" - no RDBMS I know of will allow you to get away with not specifying columns in an ON clause intended to join two tables in a non-cartesian fashion, but it might not matter...
...because typically multi tier applications these days are built with data access libraries that DO take into account the relationships defined in a database. Picking on something like entity framework, if your database exists already, then you can scaffold a context in EF from it, and it will make a set of objects that obey the relationships in the frontend code side of things
Technically, you'll never write an ON clause yourself, because if you say something to EF like:
context.Customers.Find(c => c.id = 1) //this finds a customer
.Orders //this gets all the customer's orders
.Where(o => o.date> DateTIme.UtcNow.AddMonths(-1)); //this filters the orders
You've got all the orders raised by customer id 1 in the last month, without writing a single ON clause yourself... EF has, behind the scenes, written it but in the spirit of your question where there are tables related by relation, we've used a framework that uses that relation to relate the data for the purposes thtat the frontend put it to.. All you have to do is use the data access library that does this, if you have an aversion to writing ON clauses yourself :)
It's a virtual certaintythat there will be some similar ORM/mapping/data access library for your front end language of choice - I just picked on EF in C# because it's what I know. If you're after scouting out what's out there, google for {language of choice} ORM (if you're using an OO language) - you mentioned python,. seems SQLAlchemy is a popular one (but note, SO answers are not for recommending particular softwares)
If you mean can you write a JOIN at query time that doesn't need an ON clause, then no.
There is no way to do this in SQL Server.
I am not sure if you are aware of dbForge; it may help. It recognises joinable tables automatically in following cases:
The database contains information that specifies that the tables are related.
If two columns, one in each table, have the same name and data type.
Forge Studio detects that a search condition (e.g. the WHERE clause) is actually a join condition.

Entity Framework and changing table schema/structure

I was wondering if someone knows if the following is somehow possible using EF or some other ORM.
We have a number of tables in a database. Like this one "Person"
Id
Name
Phone
Email
This is the same for all databases and will not change, it's our base table so to speak :)
Now one database might have a table also called "Person", it's the same but with an extra column Phone.
Id
Name
Phone
Email
Phone
Is there a way to have the Phone column available in the entity like a Dictionary<string,object>? I am actually only looking for basic select queries to support this. So I won't need a separate model for all databases.
Or is it just not possible? :)
--
Christian
Linq To Sql or Linq To Entities are designed to work on static table schema, I'm afraid you'll have to use ADO.NET to get what you want, or go to another schema (FK from some other tables containing key values pairs for exemple)

HowTo: Query schema objects using NHibernate?

How can I (using NHibernate) get all the entities that are joinable with certain entity?
For example:
Assume that we have the following tables as illustrated in the picture below:
The joinable tables for Customer would be Contact and CustomerType.
Assume that I'm using NHibernate and mapping each table of those to an entity in my model with the same name as the table, now, Is there is a way to get all the joinable tables for the Customer table?
NHibernate works based on the domain model, not the database model.
What you are showing there are database tables, so there's nothing to do with them using NHibernate.
Based on the previous post and on some other research, the answer is quite simply, you can't!

Is there any way to fake an ID column in NHibernate?

Say I'm mapping a simple object to a table that contains duplicate records and I want to allow duplicates in my code. I don't need to update/insert/delete on this table, only display the records.
Is there a way that I can put a fake (generated) ID column in my mapping file to trick NHibernate into thinking the rows are unique? Creating a composite key won't work because there could be duplicates across all of the columns.
If this isn't possible, what is the best way to get around this issue?
Thanks!
Edit: Query seemed to be the way to go
The NHibernate mapping makes the assumption that you're going to want to save changes, hence the requirement for an ID of some kind.
If you're allowed to modify the table, you could add an identity column (SQL Server naming - your database may differ) to autogenerate unique Ids - existing code should be unaffected.
If you're allowed to add to the database, but not to the table, you could try defining a view that includes a RowNumber synthetic (calculated) column, and using that as the data source to load from. Depending on your database vendor (and the products handling of views and indexes) this may face some performance issues.
The other alternative, which I've not tried, would be to map your class to a SQL query instead of a table. IIRC, NHibernate supports having named SQL queries in the mapping file, and you can use those as the "data source" instead of a table or view.
If you're data is read only one simple way we found was to wrapper the query in a view and build the entity off the view, and add a newguid() column, result is something like
SELECT NEWGUID() as ID, * FROM TABLE
ID then becomes your uniquer primary key. As stated above this is only useful for read-only views. As the ID has no relevance after the query.