Implementing in-memory instances of an object in NHibernate - c#

Is there anyway to implement in-memory or fixed/hardcoded object instances in NHibernate that appear to all intents and purposes to be real instances of the object read from the database?
I have a historical database that has a number of missing foreign key values against a number of different tables as they are fixed/hard coded in the old DAL.
This is causing me problems in my NHibernate mapping.
An example of this would be a fixed immutable user, say 'ADMIN' that exists in code but not in the database. This 'ADMIN' user is still used in various foreign keys so needs to exist in NHibernate so that it can manage the FK mapping.
I've managed cheat loading by using a sql view which has the hard coded rows explicitly added, but of course I can't write to a view like that so need an alternative solution.
I did find a reference to the uNhAddIns WellKnowInstanceType that seems to do something similar, but I couldn't get to to work.
Anyone have any alternative suggestions?

one trick i can think of is attaching the imaginary User instance to the session befor querying using sess.Lock(admin, LockMode.None); that should take care of the reference. But I#m not sure what happens when eager loading the reference.

Related

Incremental ETL on code first many-to-many association table

I'm setting up a data warehouse (in SQL Server) together with our engineers we got almost everything up and running. Our main application also uses SQL Server as backend, and aims to be code first while using the entity framework. In most tables we added a column like updatedAt to allow for incremental loading to our data warehouse, but there is a many-to-many association table created by the entity framework which we cannot modify. The table consists of two GUID columns with a composite key, so they are not iterable like an incrementing integer or dates. We are now basically figuring out the options on how to enable incremental load on this table, but there is little information to be found.
After searching for a while I mostly came across posts which explained how it's not possible to manually add columns (such as updatedAt) to the association table, such as here Create code first, many to many, with additional fields in association table. Suggestions are to split out the table into two one-to-many tables. We would like to prevent this if possible.
Another potential option would be to turn on change data capture on the server, but that would potentially defeat the purpose of code first in the application.
Another thought was to add a column in the database itself, not in code, with a default value of the current datetime. But that might also be impossible / non compatible with the entity framework, as well as defeating the code first principle.
Are we missing anything? Are there other solutions for this? The ideal solution would be a code first solution, or a solution in the ETL process without affecting the base application, without changing too much. Any suggestions are appreciated.

NHibernate calling "get" from a property twice

I have this situation: I'm developing a software with Spring.net and Fluent NHibernate, and I noticed something very unusual with NHibernate's behavior. I really don't know whether it's correct or not, but for my software it cannot happen. I noticed that NHibernate is calling twice all the getters, even when I'm updating something on the database. For exemple, when I try to insert some values on dabatase, NHibernate gets the value from the property to put on database, and then it triggers a new get again, which I don't know why and how is called. I think it tries to retrieve the value from cache to compare both values (database and cache) and save the updated value on cache.
By the way, for some entities I have a secondary cache level, but this situation happens with entities that have and don't have this secondaty cache level.
Any help? Thank you.
You should be able to find it out using print of current stack track
in particular getter and compare it to other traces. This should
show you starting point.
What get into my mind:
Backward get for caching because of second level cache as it stores properties of entities only.
What about has-code computing? Is it use properties to or fields?
Verification whether object in session is as same in the database.
If with get you mean NHibernate runs a select on the database to retrieve the object, within an insert/update this will be done only if you provide the ID of the object and the object is not already available within the session.
If you don't have the object in the database and want NHibernate to insert a new one, do not provide an ID and configure the generator of your ID map correctly
Otherwise make clever use of proxies and prevent NHibernate to retrieve the full object by using Load<T> which will not actually hit the database but puts a proxy into the current session scope.

Delete Cascade without explicitly referring to all dependencies

I'm building a small db-cleaner app for a QA sql server database. Naturally, I need to delete table rows with dependencies on them.
T-SQL cascading abilities are very limited, so I've tried using NHibernate to simplify matters. But, the only way I found for this was to create a collection for each dependency
in the object-to-delete, and mark that as cascade=delete.
That means creating many, many collections (both in the hbm file and in the C# object) which I don't need for any other purpose. Which makes this method as complicated as just using SQL.
Am I missing something? Is there any easier, more generic way to perform delete-cascade?
Thanks.
EDIT: Just to be clear, I avoid changing the foreign keys in the DB because it's a QA DB, designed to be identical to the production DB.
Eventually I found out a generic way to do the deletion:
This guy wrote a recursive SP which does all the work for you:
http://www.sqlteam.com/article/performing-a-cascade-delete-in-sql-server-7
Needed a little touch-ups (since my DB uses schemas) but works like a charm.
I suppose you have foreign keys defined between related tables in your database ?
You can specify at the foreign key level what should happen with related records when a parent record is being removed.
Check out MSDN for the cascading options, and how to define them:
Cascading FK constraints
Foreign Key Constraints

NHibernate multiple references to the same record from a single object

I'm using Fluent NHibernate and the setup I have is as follows:
An Address object, which is a simple list of address fields.
A Company object which has two references to address objects, MainAddress, InvoiceAddress.
The problem I'm having is that on occasion both MainAddress and InvoiceAddress may refer to the same record in the Address table.
Addresses are looked up by searching, using something along the lines of:
ICriteria c = session.CreateCriteria(typeof(Address))
.Add(Example.Create(address).ExcludeNone());
Because each Address is selected seperately, this leads to two instances of the same record, which causes NHibernate to puke when trying to save the Company object.
"a different object with the same identifier value was already associated with the session"
What's the best way to work around this?
Thanks!
Unless you are selecting in different sessions and then mixing them (which is incorrect), NHibernate's default behavior is to retrieve the same instance for the same row, no matter how many times you query.
Make sure you're using a single session.
You should use NHibernate's Merge.
merge():
if there is a persistent instance with the same identifier currently
associated with the session, copy the
state of the given object onto the
persistent instance
if there is no persistent instance currently associated with the session,
try to load it from the database, or
create a new persistent instance
the persistent instance is returned
the given instance does not become associated with the session, it
remains detached
It's the same as SaveOrUpdateCopy, but that command's apparently deprecated:
I think SaveOrUpdateCopy is something
that has exited in NHibernate for all
time and Merge is something added in
2.1 (clearly something ported from the hibernate). Anyway I am very glad that
NHibernate has this ability because
writing and handling the merge
operation manually is very boring code
to write!

Using NHibernate with ancient database with some "dynamic" tables

I have a legacy database with a pretty evil design that I need to write some applications for. I am not allowed to touch the database design at all, seeing how this is a fragile old system held together by spit and prayers. I am of course very aware that this is not how the database should have been designed in the first place, but real life some times gets in the way..
For my new application I am using NHibernate (with Fluent for mappings and NHibernate LINQ for querying) and trying to Do Things Right. So there is IoC and repositories and more interfaces than I can count. However, the DB structure is giving me some headaches.
The system is very much focused around the concept of customers, and each customer lives in a campaign. These campaigns are created by one of the old applications. Each campaign in the system is defined in a table called CampaignSettings. One of the columns of this table is simply a text column called "Table", which refers to a database table that is created at the same time as the campaign entry in CampaignSettings. The name of this table is related to the name of the campaign, which can pretty much be anything the customer wants (within the constraints given by SQL Server (2000 or 2005)). In these tables the customers live.
So that is challenge #1 - I won't know the table names until runtime. And it will change from site to site - no static mapping I guess.
To make it even worse, we have challenge #2 - this campaign table is also dynamic in structure, meaning it has a certain number of columns that are always there (customer id, name, phone number, email address and other housekeeping stuff), and then there are two other sets of columns, added depending on the requirements of the customer on a case-by-case basis.
The old applications use SQL to get the column names present in the table, then add the ones it doesn't know about as "custom fields" in the application. I need to handle this.
I know I probably can't handle these challenges simply by using mapping magic, and I am prepared to do some ugly SQL in addition to the ORM goodness that I get from NHibernate (there are 20-some "static" tables in here as well which NHibernate handles beautifully) - but how?
I will create a Customer entity that I guess I can populate manually by doing direct SQL like
SELECT * FROM SomeCampaignTable WHERE id=<?>
and then going through the columns one by one and putting stuff where it belongs. Not fun, but necessary.
And then I guess to discover the structure of the table in the first place, I could run SQL like this:
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'SomeCampaignTable'
ORDER BY ORDINAL_POSITION
And again do some manual work to configure my object to handle the custom fields.
My question is simply - how can I do this in NHibernate? Is it a simple matter of finding a way to run my own SQL, then looping through the results, or is there a more elegant way to take the pain out of it?
While I appreciate that this database design belongs in some kind of Museum of Torture somewhere, answers like "Add some views" or "Change the DB" won't help me - I will be shot if I suggest something like that.
Thanks for anything that could help save my sanity here!
You might be able to use NHibernate using Native SQL Entity Queries. Forget Linq2NH - not that I would recommend Linq2NH for any serious application.
Check this page.
13.1.2. Entity queries
https://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html/querysql.html
You could maybe do something like this:
Map your entities based on a 'fake' table to keep NHibernate happy when it compiles the mapping documents (I know you said you can't change the DB, but hopefully ok to make an empty table to keep NH happy).
Then run a query like this, as per 13.1.2 above:
sess.CreateSQLQuery("SELECT tempColumn1 as mappingFileColumn1, tempColumn2 as mappingFileColumn2, tempColumn3 as mappingFileColumn3 FROM tempTableName").AddEntity(typeof(Cat));
NHibernate should stitch together the columns you've returned with the mapped entity and give you the entity of type 'Cat' with all the properties populated. I am speculating here though, I do not know for sure if this will work, its the only way I can think of to use NHibernate for this given you don't know the tables/columns at compile time. You definitely cannot use HQL, Criteria, Linq2NH since you don't know the tables and columns at compile time, and HQL et al all convert your mappings to the mapped column names to produce the underlying SQL. Native SQL Queries are the only way I think.

Categories