I'm working with NHibernate for the first time. I have a table per class hierarchy (abstract super class). When I try to save a subclass (student) I get the error message:
[SqlException (0x80131904): Invalid column name 'Firstname' etc...]
My HBM file:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="xx"
namespace="xx.Models">
<class name="User" table="[User]" lazy="false">
<id name="UserID" column="UserID">
<generator class="native" />
</id>
<discriminator column="Type" type="String"/>
<property name="Email" column="Email" />
<subclass name="Student" discriminator-value="0">
<property name="Firstname" column="Firstname" />
</subclass>
<subclass name="Company" discriminator-value="1">
<property name="Name" column="Name" />
</subclass>
</class>
</hibernate-mapping>
SQL Code:
CREATE TABLE [dbo].[User] (
UserID INT NOT NULL IDENTITY(1,1),
Type CHAR(1) NOT NULL,
Email VARCHAR(255) NOT NULL,
PRIMARY KEY(UserID)
);
CREATE TABLE [dbo].[Student] (
UserID INT NOT NULL,
Firstname VARCHAR(255) NOT NULL,
PRIMARY KEY(UserID),
FOREIGN KEY(UserID) REFERENCES [User](UserID)
);
CREATE TABLE [dbo].[Company] (
UserID INT NOT NULL,
Name VARCHAR(255) NOT NULL,
PRIMARY KEY(UserID),
FOREIGN KEY(UserID) REFERENCES [User](UserID),
);
I am probably missing a configuration setting, the database is MS SQL, can anyone help me out?
UPDATE (related to updated question)
In a nutshell, we need mapping <joined-subclass>
instead of <discriminator>
The point is, that we use mapping for 8.1.1. Table per class hierarchy while we need
(few cites)
A table-per-subclass mapping would look like:
<class name="IPayment" table="PAYMENT">
<id name="Id" type="Int64" column="PAYMENT_ID">
<generator class="native"/>
</id>
<property name="Amount" column="AMOUNT"/>
...
<joined-subclass name="CreditCardPayment" table="CREDIT_PAYMENT">
<key column="PAYMENT_ID"/>
...
</joined-subclass>
<joined-subclass name="CashPayment" table="CASH_PAYMENT">
<key column="PAYMENT_ID"/>
...
</joined-subclass>
<joined-subclass name="ChequePayment" table="CHEQUE_PAYMENT">
<key column="PAYMENT_ID"/>
...
</joined-subclass>
</class>
Four tables are required. The three subclass tables have primary key associations to the superclass table (so the relational model is actually a one-to-one association).
Similar to this we need mapping like this:
<class name="User" table="[User]" lazy="false">
<id name="UserID" column="UserID">
<generator class="native" />
</id>
<joined-subclass name="Sutdent" table="Student">
<key column="UserID"/>
<property name="Firstname" column="Firstname" />
...
</joined-subclass>
</class>
ORIGINAL part (related to original question)
In this case, the error should be really clear: There is missing column 'Firstname'
. Because with the table per class hierarchy we simply must have all columns in our table. It is ONE table per complete hierarchy. No other place/table where to persist data...
8.1.1. Table per class hierarchy
Exactly one table is required. There is one big limitation of this mapping strategy: columns declared by the subclasses may not have NOT NULL constraints.
And in case, that you are asking: How can NHibernate update DB schema for me? please check this:
(small extract, see the above link for all details)
Configuration cfg ...
cfg.Configure();
...
var update = new SchemaUpdate(cfg);
update.Execute(true, false);