Nhibernate in Delfshell

advertisement
NHibernate in
DeltaShell
Wat is NHibernate?
• Object-Relational Mapper
Geheugen / Class/ .Net CLR object
Database /tabel(len)/ rijen
Waarom NHibernate?
• Abstractie boven de DB (dbagnostisch)
• Minder onderhoud dan sql queries
• Rijk, ‘oud’ port van Java Hibernate
• Lazy loading, dirty checking etc
• Schema-export /update
Configuratie: via app.config
<configSections>
<section name="hibernate-configuration"
type="NHibernate.Cfg.ConfigurationSectionHandler,NHibernate"/>
</configSections>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.provider">
NHibernate.Connection.DriverConnectionProvider
</property>
<property name="dialect">
NHibernate.Dialect.MsSql2005Dialect
</property>
<property name="connection.driver_class">
NHibernate.Driver.SqlClientDriver
</property>
<!-- local -->
<property name="connection.connection_string">
Server=xp;initial catalog=DataManagerTest;Integrated Security=SSPI
</property>
<property name='proxyfactory.factory_class'>
NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu
</property>
</session-factory>
</hibernate-configuration>
Configuratie : in code
(runtime)
• (Her)Configureren via properties
• Toevoegen mappings (AddAssemblie)
• Bepalen naming-strategies
• Toevoegen DataAccessListeners
NHibernate entititeiten
Configuration
SessionFactory
•Mappings
•Connection String
•Settings
•OpenSession
Session
•Load()
•Save()
•Transactions
Voorbeeld: VM opslaan en
app.config
Nhibernate object states
Configuratie : mapping files
• 1 hbm.xml file per class
• Voeg NHibernate.xsd’s toe aan VS
• Embedded resource!!
• Zeg zo weinig mogelijk in je
mappings
• Surrogaat key ID
Voorbeeld mapping : Profile
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="IETObjects"
assembly="IETObjects">
<class name="Profile" lazy="false" >
<id name="DatabaseID" unsaved-value="0" column="ID" type="integer" >
<generator class="native"/>
</id>
<property name="Url" />
<property name="Name" />
<property name="Language" />
<property name="LoginOnce" />
<list name="Screens" cascade="all-delete-orphan" lazy="false" >
<key column="profile_id"/>
<index column="screen_profile_index" />
<one-to-many class="IETObjects.Screens.Screen" />
</list>
<many-to-one class="Administrator" name="Administrator" />
</class>
</hibernate-mapping>
Verschillende relaties
• One-to-many (Map.Layers)
– Foreign key in child-table
– Mapping : In Set,List Bag mapping van
parent
• Many-to-one
(CoverageLayer.Coverage)
– Foreign key in child-table
– Mapping : in childmapping
Verschillende relaties 2
• Many-to-many (Variable>Arguments)
– In aparte koppel tabel
– Mapping : in Collectie element (List,Set
bag etc)
• One-to-One
– Relatie tussen primary keys
– Mapping: in Parent (Person.Address)
– Not recommended (lazy etc)
One-to-many
• Parent / Child Map / Layer
• Mapping in collectie in parent:
One-to-many : tabellen
Many-to-one
• Mapping in child
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="IETObjects.Answer, IETObjects" >
<id name="DatabaseID" unsaved-value="0" column="ID" type="integer" >
<generator class="native"/>
</id>
<property name="TotalAnswer" />
<many-to-one name="Case" column="caseID" not-null="true" />
<many-to-one name="User“ column="userid" not-null="true"/>
</class>
</hibernate-mapping>
Many-to-one : tabellen
Many-to-many
• Mapping aan een of beide kanten
<class name=“Artist" >
<id name="Id" column="id" type="System.Int64" unsaved-value="0">
<generator class="increment" />
</id>
<list name=“Concerts" table=“artist_concerts" >
<key column=“artist_id"/>
<index column=“artist_list_idx" />
<many-to-many class=“Concert" column=“concert_id" />
</list>
</class>
Many-to-many : tabellen
Any-type mappings
• Foreign key naar willekeurige tabel
• Mapping in ‘parent’ (a la many-toone)
<class name="Order"
table="Orders">
<id name="Id">
<generator class="native"/>
</id>
<any name="Payment" id-type="System.Int64" meta-type="System.String" cascade="all">
<meta-value value="CreditCard" class="CreditCardPayment"/>
<meta-value value="Wire" class="WirePayment"/>
<column name="PaymentType"/>
<column name="PaymentId"/>
</any>
</class>
Any-type : tabellen
• Geen ‘echte’ foreign keys
• Restrictie in primary key type van gemapped classes
• Uitzonderings situatie, vaak is er een betere oplossing
Inheritance
• Table-per-classhierarchy
• Table-per-subclass
• Table-per-concrete-class
Inheritance: table-perclasshierarchy
• Alle entiteiten in 1 tabel
• Subclass met discriminator
• Discriminator column voor types
• Goede performance
• Sparse tabel
• Ongewilde relaties tussen subclasses
(column types)
Inheritance: table per
concrete class
• Geen associaties op base class
niveau
• Union-subclass
• Niet genormaliseerd
• Zelfde property in veel tabellen
Inheritance : table-persubclass
• Meest OO (weinig redundantie)
• Geen wijziging base-class tabellen
• Lage performance
• Join(s) voor enkele entiteit
Inheritance :kiezen
• Table-per-classhierarchy
– Simpel : 1st keus
• Table-per-subclass
– Als optie 1 te groot of als er een
duidelijke scheiding in het schema moet
komen
• Table-per-concrete-class
Acces-strategies
• Property : default map naar public
property
• Field: map naar field. Geef fieldnaam
op in mapping (als geen naming
strategie)
• NoSetter: als field maar gebruikt
property voor Get (Readonly)
• Custom (eigen class)
Naming-strategies
• Hoe kom ik van een public property
naar het bijbehorende field?
– Camelcase
– Camelcase_
– Lowercase
–…
Acces strategy
<joined-subclass name="DataItemSet" >
<key column="folder_item_id"/>
<property name="Tag" access="nosetter.camelcase" />
<!--ensures a list is created on load-->
<!--<property access="field" name="isSynchronizedWithList"/>-->
<!--type of the list to create EventedList<T> -->
<!--<property access="field" name="listType" />-->
<property name="itemType" access="field" />
/joined-subclass >
</joined-subclass>
Cascade object relaties
• Eigenaar van object? Zet een cascade op.
• Object relaties :many-to-one,one-to-many,many-to-many
• Opties
– All :save-update-delete van relatie
– Save-Update : geen delete
– All-delete-orphan: all+als een object uit alle collecties delete het
(orphan)
– None: object zorgt voor zichzelf
Lazy classes
• Default is lazy!
• Alle public accessors (methods
properties) moeten virtueel.
• Proxy objecten
• Open session is nodig (onhandig voor
web)
Usertypes
• Alleen als niet als anders kan
• Custom opslag van en naar byte[]
• Geen foreign keys
• Geen updates
• Voorbeeld : GeometryUserType
DeltaShell: Database
structuur
Project
Folder
Model
DataItem
Coverage
Map
Layer
•Project is root
•Zorg voor juiste ‘cascade’ regels zodat je object opgeslagen wordt.
DataItem Value Types
• Any type mapping: foreign key naar meerdere tabellen
• Zorg er voor dat je object wordt teruggeven door een
DataProvider.SupportedDataObjectNames
DataAccessListeners
• Run code bij bepaalde database acties (pre-insert, postload etc)
• Nu alleen FileBased DAL.
– Herschijft bestands namen
– Reconnect bij save-as
public bool OnPreInsert(object entity, object[] state, string[] propertyNames)
{
if (entity is IFileBased)
{
MakePathRelative(entity as IFileBased, state, propertyNames);
}
return false;//no veto
}
Mappen van Modellen
• Voeg modeldata toe in DataItems
• Map de modeldata data classes
• Zorg ervoor dat deze classes in de
any-type van DataItem terecht
komen via dataProviders.
• OF : maak custom mappings
NHibernate binnen test
• NHibernate configuratie is static
• Voeg zelf assemblies toe met
– NHibernateProjectRepository.RegisterAssembly()
• Voeg DataItem ValueType mappings toe met
– NHibernateProjectRepository.RegisterDataItemValueType
• Reset static configuratie met
– NHibernateProjectRepository.ResetConfiguration()
Veel voorkomende fouten
• Key not found exception ->
DataItemType
• Event registratie en Nhibernate
– Nhibernate set properties dus
unsubscribe/subscribe daar.
• Unmapped class
– Geen embedded resource?
Nhibernate Profiler
• Demo in VM.
• Download trial van Ayende
NHibernate Linq
• IQueryable  SQL 
• Demo2 in VM
Nog meer!!?
• NHibernate in Action van manning
• Ayende’s blog
• ActiveRecord
• Fluent-Nhibernate
Download