I have
- Contact class with joined inheritance
- Counterpart class extending Contact
- Customer extending Counterpart
- field 'code' in Customer I would like to be unique
Why is CUBA studio does not allow me to tick the 'unique' checkbox for the 'code' field ?
Probably your entities implement the SoftDelete interface. It means that unique constraints must either include the DELETE_TS field or have a where condition with this field (depending on the database type).
In case of JOINED inheritance strategy the DELETE_TS field exists only in the root table, so the automatic creation of unique constraints is impossible for child entities.
You can create any constraints manually in the 30.create-db.sql script, but keep in mind that if the unique index does not consider the soft deletion mark, users will not be able to create a new record with the same CODE as in a deleted record.
Related
I am going through a pluralsight course that is currently going through building an MVC application using an entity framework code-first approach. I was confused about the Database schema used for the project.
As you can see, the relationship between Securities and it's relating tables seems to be one-to-one, but the confusion comes when I realize there is no foreign key to relate the two sub-tables and they they appear to share the same primary key column.
The video before made the Securities model class abstract in order for the "Stock" and "MutualFund" model classes to inherit from it and contain all relating data. To me however, it seems that same thing could be done using a couple of foreign keys.
I guess my question is does this method of linking tables serve any useful purpose in SQL or EF? It seems to me in order to create a new record for one table, all tables would need a new record which is where I really get confused.
In ORM and EF terminology, this setup is referred to as the "Table per Type" inheritance paradigm, where there is a table per subclass, a base class table, and the primary key is shared between the subclasses and the base class.
e.g. In this case, Securities_Stock and Securities_MutualFund are two subclasses of the Securities base class / table (possibly abstract).
The relationship will be 0..1 (subclass) to 1 (base class) - i.e. only one of the records in Securities_MutualFund or Securities_Stock will exist for each base table Securities row.
There's also often a discriminator column on the base table to indicate which subclass table to join to, but that doesn't seem to be the case here.
It is also common to enforce referential integrity between the subclasses to the base table with a foreign key.
To answer your question, the reason why there's no FK between the two subclass instance tables is because each instance (with a unique Id) will only ever be in ONE of the sub class tables - it is NOT possible for the same Security to be both a mutual fund and a share.
You are right, in order for a new concrete Security record to be added, a row is needed in both the base Securities Table (must be inserted first, as their are FK's from the subclass tables to the base table), and then a row is inserted into one of the subclass tables, with the rest of the 'specific' data.
If a Foreign Key was added between Stock and Mutual Fund, it would be impossible to insert new rows into the tables.
The full pattern often looks like this:
CREATE TABLE BaseTable
(
Id INT PRIMARY KEY, -- Can also be Identity
... Common columns here
Discriminator, -- Type usually has a small range, so `INT` or `CHAR` are common
);
CREATE TABLE SubClassTable
(
Id INT PRIMARY KEY, -- Not identity, must be manually inserted
-- Specialized SubClass columns here
FOREIGN KEY (Id) REFERENCES BaseTable(Id)
);
I have a class A and a class B that inherits from A. Class A has a certain attribute X. Class B adds another attribute Y. An instance of B is uniquely identified by its pair of attributes {X,Y}. So, {X,Y} is a candidate key for class B. Obviously this key doesn't exist at the class A level since attribute Y isn't there. I use a surrogate key for class A.
Now, I use Hibernate for the object-relational mapping. If I use the TABLE PER SUBCLASS inheritance strategy, I don't see a possibility for defining a UNIQUE constraint on multiple attributes that belong to different classes (and then in the DB, to different tables).
My question is how can I define a unique constraint for this candidate key using Hibernate and more generally in SQL? If it's not possible, what do you recommend?
Thanks
Here are two solutions:
Create a new table with one column which is its PK. This table should hold all the values which you want to make unique. Create foreign keys to this table which will ensure that the domain on the columns comes from the unique table.
Create triggers which raise an error if the condition is violated.
I am supposed to be shipping out a box with variable contents and tracking this in a database. All of my items (the contents of a box) are different types and require different tables to track their respective pieces of information, although each item type has the same length serial number (i.e. PK are the same datatype). And I have a Boxes table.
So each item has a table (~7 tables) plus the box table. I want to create a BoxContents table. I tried to make a many-to-many relationship intermediate table with two columns: one for BoxID and one for ItemBarcode, where BoxID is a FK to the PK on the Boxes table and the ItemBarcode is a FK to each of the PKs on the Items tables (i.e. I tried to link multiple tables to the same column). Unsurprisingly this didn't work. I tried to insert an item and the FK constraint was violated on all but one of the ItemBarcode relationships.
How can I construct my relationships to link several types of items to one box in one table? Is this a logical approach? Do you need more information?
You need a category hierarchy (aka. class hierarchy, subtype hierarchy, inheritance hierarchy...):
There are 3 main strategies for implementing a category hierarchy. If you choose "all classes in one table" or "class per table", then no matter how many kinds of items you have, you only need one "link" table to implement the many-to-many relationship.
My first choice, if the ItemBarcode values are truly unique, would be to:
EDIT: Added description of required triggers.
Add triggers to enforce the barcode uniqueness.
(An insert/update trigger on each item table needs to verify that all (newly) assigned barcodes do not appear in other item tables.)
Use a single BoxId/ItemBarcode table without a FK relation on the barcode side, but with triggers to ensure it remains valid.
(An insert/update trigger on the association table needs to verify that the barcodes exist in the item tables. A delete trigger on each item table needs to prevent, or cascade, deletion of items that are in the association table. An update trigger on the item tables needs to update and changed barcodes in the association table. This last may be integrated into the insert/update trigger in the prior bullet.)
Consider using a view of all items to access common data by ItemBarcode.
My second choice would be n BoxId/ItemBarcode tables for the n item types. Straightforward, but a bit busy. It makes adding a new item type messier than it needs to be.
I would not use a BoxId/ItemTypeId/ItemBarcode table. It denormalizes the data by associating the ItemTypeId and ItemBarcode again, it doesn't allow the use of a FK on the barcode side, and it still requires triggers to ensure integrity.
Don't be afraid of triggers. There are some problems that they can address quite effectively.
Relational databases are not good with this kind of problem. Your basic design is correct - an association table for FKs between the tables.
Your choices are:
Have multiple columns in your association table - one for for each item table
Merge the item data into one item table
I would go option 2.
I'm attempting to design a schema for a consignment store's POS system. I have a master item's table and multiple entities that reference it as a foreign key and contain different attributes. The items table contains all of the information that is common to all items, regardless of its type. The entities that reference any given item offer a specific attribute for that given item type. For example, a "split" item needs an asking price, while a store item needs a cost price.
While this design technically works and enforces only one item in the items table, I'd like to be able to maintain that any given item is only referenced by ONE of these entities. The concern is that I don't want a "split" item to also me considered a "store" item accidently. Is there any way to enforce this through schema design?
The ERD is here: http://randywestergren.com/pos-erd.pdf
The tables in question are phppos_items, phppos_items_entity_split, phppos_items_entity_store, etc.
Thanks in advance!
It seems like you're determining whether or not a item is a "split" or a "store" type by which related row exists. Instead, how about adding a type field to the items table? It won't prevent the other related row from actually existing, but it will let you know definitively that it's an error.
Create a secondary table:
typed_items (poorly named)
{
PK: item_key - this points to the item
PK: int item_type_id - this type code specified which 'type' of item, ie: store, split
// optional, depending on your key design:
// 1...n FK:
// split_item_id,
// store_item_id,
// etc.., if you reference the items PK in the sub-item-type-detail tables, this
// isnt nessicary. if you are using a synthetic key on the sub-item-type-detail
// tables and no key relationship exists you can use this table as a linking table,
// otherwise its not nessicary
}
Since type items key and the type descriminator id are part of a primary key, you know that your model will not allow an item to belong to 2 different sub-item-type-detail tables.
If you want (paranoid) integrity you can now add a constraint on these type-detail tables that ensures the item's key paired with the constant type descriminator value for that type exists in this table.
I am just starting out with ADO.net Entity Framework I have mapped two tables together and receive the following error:
Error 1 Error 11010: Association End 'OperatorAccess' is not mapped. E:\Visual Studio\projects\Brandi II\Brandi II\Hospitals.edmx 390 11 Brandi II
Not sure what it is I am doing wrong.
I believe I can add some more clarity to the issue (learning as I go):
When I look at the Mapping details and look at the association, the column for operatoraccess table (from above) is blank and the drop down only includes field from the linked table.
The Entity Framework designer is terrible - I've had the same problem many times (and your problem too, Craig):
This happens when you have a many-to-one association which is improperly setup. They could very easily fix the designer to make this process simple; but instead, we have to put up with this crap.
To fix:
Click on the association, and go to the mapping details view.
Under association, click on Maps to <tablename>. Choose the table(s) which make up the many side of the relationship (ie. the table(s) which make up the *-side of the association in the designer)
Under Column, choose the table-columns which map to each entity-side Property. You get this error when one of those entries are blank.
I had the exact same problem and this is what I did to fix it.
Make sure you have an Entity Key set in your designer on the tables your making an association with. Also check that StoreGeneratedPattern is set to Identity for that Entity Key.
There's not a lot of information in your question, but, generally speaking, this means that there is an incompletely defined association. It could be that you have tried to map one table with a foreign key to another table, but have not mapped that other table. You can also get this error when you try to do table per type inheritance without carefully following the steps for implementing that feature.
Not sure of the answer, but I've just posted a similar question, which may at least help clarify the issue you are experiencing.
Defining an Entity Framework 1:1 association
I had to go back into the database itself and clarify the foreign key relationship
I had this problem in the case where I was creating both many to 0..1 and 0..1 to 0..1 associations. One entity needed associations to multiple tables, and that entity did not have foreign keys defined for those tables.
I had to do the table mappings step that is given in the accepted answer, but note that it wasn't only for many to many associations; it applied to all the types of associations I added for this entity.
In the Mapping Details view, I had to select the entity with the non-foreign key ID columns to the various tables. This is not always the "many" side of the relationship. Only there was I able to map the related entity property to the appropriate property in the original entity. Selecting the "destination" entity would not allow me to select the properties that I needed to, and the error would still exist.
So in short, I had to map using the table related to the entity that had the "non-foreign key" ID fields corresponding to the various entities' (and their tables') primary keys that I needed to associate.
Entity A
various other properties...
Id
ContactId
OrderId
etc.
Contact entity
Id
FirstName
LastName
etc.
In the mapping details, I selected Entity A's table. It then showed both ends of the association. I mapped its Entity A's Id property to its table's actual ID column (they had different names). I then mapped the Contact entity's Id field to the ContactId field on the A entity.
Simply select the many relationship table (*) from the Association>Edit Mapping & select the appropriate relationship