using NHibernate on a table without a primary key - nhibernate

I am (hopefully) just about to start on my first NHibernate project and have come across a stumbling block. Would appreciate any advice.
I am working on a project where my new code will run side-by-side with legacy code and I cannot change the data model at all. I have come across a situation where one of the main tables has no primary key. It is something like this:
Say there is an order table and a product table, and a line_item table which lists the products in each order (i.e. consits of order_id, product_id, and quantity). In this data model it is quite possible to have 2 line items for the same product in the same order. What happens in the existing code is that whenever the user updates a line item, all line items for that order are deleted and re-inserted. Since even a compound key of all the fields in the line_item table would not necessarily be unique, that is the only possible way to update a line item in this data model.
I am prepared to guarantee that I will never attempt to update or delete an indivdual line item. Can I make my NHibernate code work in the same way as the existing code? If not, does this mean I (a) I cannot use NHibernate at all; (b) I cannot use NHibernate to map the line_item table; or (c) I can still map this table but not its relationships
Thanks in advance for any advice

I think if you map it as a bag collection on the Order (with inverse="false") it would work.
Collection Mapping
Note: Large NHibernate bags mapped
with inverse="false" are inefficient
and should be avoided; NHibernate
can't create, delete or update rows
individually, because there is no key
that may be used to identify an
individual row.
They warn against it but it sounds like what you want.

Related

How can I replicate many to many relationship

I have a product database where I am trying to replicate a particular product's data and relationships to a new product, a clone. I am puzzled however on how to replicate several many to many relationships. For example, consider a product with two parts, and for each part, their are several colors available. I have a Product table, a product Areas table, and a Colors table. The product id is a foreign key in the area table, one to many. The Area table has an area id (pk) along with other descriptive fields, and the Colors have color ids (pk) along with palette information. A fourth table serves as the many to many look up table, it's primary key being the part id and the color id combined. This is a pretty straight forward configuration as far as it goes.
I can't think of a way to clone this structure, however, despite many approaches which would be way too much to elaborate upon here. I can easily enough replicate the left hand, product-area relationship, generating new AreaIDs (A,B,C). But in a next step, I then want to replicate the many-to-many relationship using the new area ids. However, now I don't know which original ID (H,L,W) to associate with which new ID.
For example, does the new id A get mapped to the set of colors from the old ID H, L, or W? I have only id's to work with. I can select both parts and part-color pairs from the source in one select statement, but I can't insert into two tables with one statement.
In other words, how do I replicate many to many relationships if I want to supply a new ID for half of it? Do I have to resort to cursors? I can if I need to, but I'm imagining there an elegant way to accomplish this that I just can't figure out. Maybe using a temp table or some sort of table valued function? I've tried to search for answers, but I all I can find is advice on setting up many-to-many relationships.
Thanks for you experts who have the patience to read through this question.
SymmetricDS replicates tables that have many into many relationships using change data capture. The key is to perform an initial load to get the databases in sync initially so that if a child record is updated the change data capture will also work. In the latest versions of SymmetricDS (3.10 and higher) it will also auto resolve foreign key errors if the databases are not in sync. If a child row is being loaded to a target without the parent it will callback to the source to load the missing parent as well so that you do not need to intervene.

database design, items and orders tables

I was just after some input on database design. I have two tables, Orders and Items.
The items table is going to be a list of items that can be used on multiple orders, each item has an id
The way i thought to do it at the moment, was in the order to put an array of comma seperated ids for each item in the order.
does that sound like the best way?
also im using linq to entity framework and i dont think id be able to create a relationship between the tables, but i dont think one is needed anyway is there, since the items are not unique to an order
Thanks for any advice
The way I thought to do it at the moment, was in the order to put an array of comma separated ids for each item in the order. Does that sound like the best way?
Absolutely not - It will be MUCH more difficult in SQL to determine which orders contain a particular item, enumerate the items (to get a total, for example), and to add/remove items from an order.
A much better way would be to create an OrderItem table, which has a foreign key back to Order and Item and any other attributes relating to the item in that order - quantity, discount, comments, etc.
As far as EF goes, it will probably create a third entity (OrderItem) that will "link" the two tables. If you don't add any extra properties (which you probably should) then EF will probably create it as a many-to-many relationship between the Order and Item entities.
As far as I have understood from your question (it is not very clear), every Order can have multiple Items and every Item can be used in multiple orders. If this is what you want, you have a many to many relationship, that must be resolved using an intersection entity. This intersection entity has 2 foreign keys, one for item and one for order. Using it, you can identify what items are in a certain order and what orders need a certain item.
As my explanation is very short and very sloppy, I will recommend you the following references:
http://sd271.k12.id.us/lchs/faculty/bkeylon/Oracle/database_design/section5/dd_s05_l03.pdf
Resolve many to many relationship
Also, you proposed design is very bad, as it breaks the first normal form: no attribute can have multiple values. You shoud try to build databases at least in third normal form.
Regarding the database design, you would usually create a third table - ORDER_ITEMS - linking the two tables, containing columns (foreign keys) for order id and item id. You might also want to include a column for quantity.

SQL Server Business Logic: Deleting Referenced Data

I'm curious on how some other people have handled this.
Imagine a system that simply has Products, Purchase Orders, and Purchase Order Lines. Purchase Orders are the parent in a parent-child relationship to Purchase Order Lines. Purchase Order Lines, reference a single Product.
This works happily until you delete a Product that is referenced by a Purchase Order Line. Suddenly, the Line knows its selling 30 of something...but it doesn't know what.
What's a good way to anticipate the deletion of a referenced piece of data like this? I suppose you could just disallow a product to be deleted if any Purchase Order Lines reference it but that sounds...clunky. I imagine its likely that you would keep the Purchase Order in the database for years, essentially welding the product you want to delete into your database.
The parent entity should NEVER be deleted or the dependent rows cease to make sense, unless you delete them too. While it is "clunky" to display old records to users as valid selections, it is not clunky to have your database continue to make sense.
To address the clunkiness in the UI, some people create an Inactive column that is set to True when an item is no longer active, so that it can be kept out of dropdown lists in the user interface.
If the value is used in a display field (e.g. a readonly field) the inactive value can be styled in a different way (e.g. strike-through) to reflect its no-longer-active status.
I have StartDate and ExpiryDate columns in all entity tables where the entity can become inactive or where the entity will become active at some point in the future (e.g. a promotional discount).
Enforce referential integrity. This basically means creating foreign keys between the tables and making sure that nothing "disappears"
You can also use this to cause referenced items to be deleted when the parent is deleted (cascading deletes).
For example you can create a SQL Server table in such a way that if a PurchaseOrder is deleted it's child PurchaseOrderLines are also deleted.
Here is a good article that goes into that.
It doesn't seem clunky to keep this data (to me at least). If you remove it then your purchase order no longer has the meaning that it did when you created it, which is a bad thing. If you are worried about having old data in there you can always create an archive or warehouse database that contains stuff over a year old or something...
For data like this where parts of it have to be kept for an unknown amount of time while other parts will not, you need to take a different approach.
Your Purchase Order Lines (POL) table needs to have all of the columns that the product table has. When a line item is added to the purchase order, copy all of product data into the POL. This includes the name, price, etc. If the product has options, then you'll have to create a corresponding PurchaseOrderLineOptions table.
This is the only real way of insuring that you can recreate the purchase order on demand at any point. It also means that someone can change the pricing, name, description, and other information about the product at anytime without impacting previous orders.
Yes, you end up with a LOT of duplicate information in your line item table..; but that's okay.
For kicks, you might keep the product id in the POL table for referencing back, but you cannot depend on the product table to have any bearing on the paid for product...

One-to-one relationship or One-to-many?

Maybe I need more coffee this morning but here goes...
I have a very simple inventory system. Right now I have two tables: Items and Inventory.
Items
Id
Title
YearReleased
Inventory
Id
ItemId(Foreign key to Items)
Quantity
QuantityOnHand
Each item has one inventory and each inventory belongs to one item. The relationship between the two is one-to-one. However, when I diagram this out, the relationship based on my setup thus far is a one-to-many, due to the auto-incrementing id I have for Inventory.
Now, I could make this one-to-one by eliminating the auto incrementing id in the Inventory table, but this makes me feel dirty. I always use internal id's for primary keys.
I see a few options:
1.) Remove the auto incrementing id field in Inventory and live with the dirty feeling.
2.) Keep the tables as-is.
3.) Merge Items and Inventory into one table: ItemsInventory.
4.) Something else?
If your relationship is really one to one, drop the Id from the Inventory table and use ItemId as PK and FK. Also, name both keys ItemId -- helps.
If you're certain that the mapping will always be 1:1, then merge the two tables into one.
However, are you certain that the relationship will allways be 1:1?
Since many ORMs require a single auto-increment PK, I would:
4) Add a unique index to Inventory.ItemId and it should show as a one-to-one relationship.
Would making ItemId have a constraint to be unique be insufficient? That seems to satisfy your requirements.
If what the table structure you have mentioned is going to remain as it is now, then I think you should merge Items and Inventory into one table: ItemsInventory.
For such small tables it doesn't make sense to partition them vertically. That way you would remove an extra join. Select on a single table is always faster then joins.
I would merge the two tables together my main reason is you will have duplicate data as
well as unnecessary data if you stick with two tables. Querying will also be faster! Looking at the two tables I would merge into one for sure.
Items
Id
Title
YearReleased
Inventory
Id
ItemId(Foreign key to Items)
Quantity
QuantityOnHand
You will have two less collumns full of data if you merge to one table ("ID" ItemID" can be dropped). Writing your logic to retrive and send data to the database will also be easier for you.
I would have this table:
**ItemsInventory**
Id
Title
YearReleased
Quantity
QuantityOnHand
However you must be sure it is a one-one otherwise you may have give yourself a lot of work if the bussiness needs change.
Simon
If you really want to make it a simple inventory system, then merge the tables.
Reasons not to merge the tables/it doesn't stay simple.
How many items will NOT have an inventory record? Your example only shows a few inventory fields and maybe that's all it would ever have. But it the fields you track in inventory grow and there is a large part of items not in inventory, you're going to have a lot of null fields.
How often will inventory get updated? If these fields are a result of other transaction tables (purchases and sales) being updated frequently, no reason to constanatly update the items table just because inventory was purchased or sold. In your current system, users are expecting these values to be real time (If not then they know what isn't up to date since they didn't make the changes.).

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.