I define my data model using Fluent nHibernate POCO classes + mappings. I'm also using nHiberate schema to create database schema.
All is working fine but there is one unpleasent fact.
When I use many-to-one reference referece is named by something similair to GUID instead of any descriptive name.
Here's a piece of SQL:
alter table [Odbiorca]
add constraint FK291D244B5D9E8115
foreign key (Adr_IdKraj)
references [Kraj]
I want nHiberate to generate something like Sql Studio does like [FK_Odbiorca_Kraj].
Is it doable by overridding mappings or by creating any convention?
I don't know Fluent, but with regular XML mapping you just can use the foreign-key attribute:
<many-to-one
name="Kraj"
class="Kraj"
column="Adr_IdKraj"
foreign-key="FK_Odbiorca_Kraj"/>
Related
Is there a way to map property with database column with custom column, that IS NOT a FK, just a candidate key ( it is unique for table )?
If not, what is my options here? (need to restrict select results with joined table restrictions)
NHibernate supports feature called property-ref. It is documented here: 5.1.10. many-to-one. Some extract:
The property-ref attribute should only be used for mapping legacy data
where a foreign key refers to a unique key of the associated table
other than the primary key. This is an ugly relational model. For
example, suppose the Product class had a unique serial number, that is
not the primary key. (The unique attribute controls NHibernate's DDL
generation with the SchemaExport tool.)
So, if the child table contains for example Guid, which is the same as in the target parent table... this could solve the issue. Example mapping:
<many-to-one name="Parent" property-ref="ParentGuid" column="THE_GUID_COLUMN"/>
Using the fluent syntax, it could look like this:
References(x => x.Parent)
...
.PropertyRef("ParentGuid")
.Column("THE_GUID_COLUMN");
Anyhow, this is not ideal and should be used mostly for solving legacy stuff.
I am using Fluent NHibernate (which I am fairly new to) in an application I am developing using a legacy Oracle DB. The DB has composite keys which are comprised of foreign keys and database generated columns. The generated columns are supplied by calling a DB function with the table name, and one of the other foreign key parts. The generated composite key parts are not unique, and I cannot change this. The generated key parts are often used as foreign keys on other tables too.
If I create entity mapping which specifies the composite key as it is in the database, then we cannot use any identity generation strategies, which breaks unit of work
If I create entity mapping which specifies only the generated column as the primary key, then I can use trigger-identity to generate the ids, and I get unit of work, but I then have a problem when I want to update, or access a child collection: The other parts of the key are not included in the WHERE statement.
Can anyone give me any advice on how to proceed?
If I stick with mapping composite keys, can I extend nhibernate to output the SQL to use trigger-identity? If so, can you suggest a starting point?
If I map a single column key, can I include other properties in a WHERE clause for HasMany mapping and Updates?
Unfortunately, as you have already found out, there is no support at all for this setup.
My suggestion is to do INSERTS manually (using custom SQL, for example). And yes, this breaks the UoW, but that is true of identity too.
I have a mapping in FluentNHibernate for a HasMany relationship and I'd like to specify a Table on it to override the default Table that nHibernate will look in to find those objects that I have many of. Does that make sense?
So lets say I have a table for Invoices and a table for InvoiceItems and lets say I have table called InvoiceItemsTwo.
I have a class for Invoice and a Class for InvoiceItems as well, and their mappings are pretty straight forward. I'd like to specify in my mapping for Invoice, that it should look for it's items in InvoiceItemsTwo instead of the default InvoiceItems.
So my mapping of that relationship looks like this
HasMany(c => c.InvoiceItems).Cascade.SaveUpdate().Table("InvoiceItemsTwo");
But this doesn't work. I keep getting an error from my website at runtime that says Invalid object name 'InvoiceItems'.
Why is it ignoring the fact that I am explicitly specifying the Table in my mapping on the relationship?
I tried dumping the mapping at run time and it's being setup something like this
<bag cascade="save-update" table="InvoiceItemsTwo">
Any ideas?
The table attribute applies only to many-to-many relationships, not one-to-many.
you can't specify a different table in your mapping class. Fluent NHibernate uses the class mapped on the property list (InvoiceItems).
If yoy want to use another class to map your details table you must create a InvoceItemsTwo class and map it in your master table class.
You could map the list as composite-element instead of a one-to-many relation and then map it to another table. But it is not a good idea. Consider that NH needs to know where to store an object which is in memory. So it may happen that the object is stored in the wrong table.
Either store all the InvoiceItems in separate tables using composite-element instead of one-to-many and components instead of many-to-one (however this is called in Fluent).
Or store all the InvoiceItems in the same table and use regular references.
For our test fixtures we use NHibernate to generate a database schema. We have a slight strange case in which an entity references a another entity but we don't wish to have a foreign key constraint (it should be possible to delete the referenced entity so a foreign key cannot be used).
Is it possible to specify that the generated schema does not have a foreign key for a particular relationship?
Jay-
If you're using Fluent NHibernate, you can set this in either your implementation of IHasManyConvention or IReferenceConvention (if using conventions).
Cascade.SaveUpdate() should propagate the saves and updates, but leave the orphaned child objects when the parents are deleted.
In standard NHibernate HBM files, I believe the tag for a bag should look like:
<bag cascade="save-update" name="EntityName"> ... </bag>
UPDATE: Here's an informational post by Ayende on the topic of orphaning child objects and the differences with the cascade values.
I need to use tables from a DB which I cannot alter (using linked server).
So part of my schema is a view on these table and I cannot create an FK in my DB.
When I come to creating the association in ADO.NET Entity Framework I am getting problems because a second column on the table from the external DB has an index on it and the EF is creating an Entity Key for it (it's the name descr of the record - I think they just wanted to speed the ordering on it).
When I take the Entity Key off this column in the EF entity it complains that I need it because the underlying table has a key on it.
If I leave it in I cannot map it onto anything in the table mapping of EF.
Does anyone know what I should do please?
You will have to edit the XML and remove the column from the key. Find the <EntityType> tag in the <edmx:StorageModels> section (SSDL content). Delete any <PropertyRef> in the <Key> that is not actually part of the primary key.
Once you do this, you can set "Entity Key" on the corresponding scalar property in the designer to false, and EF won't get mad. You will also not be asked to map this column in associations anymore.