NHibernate Envers - how to audit revisions on a separate database? - c#

I'm using Nhibernate Envers and I want Envers to save audit info on a separate database to keep things cleaner/more maintainable.
I'm using this fluent configuration:
var enversCfg = new NHibernate.Envers.Configuration.Fluent.FluentConfiguration()
enversCfg.Audit(GetDomainEntities())
nhCfg.SetEnversProperty(ConfigurationKey.DefaultCatalog, "nhibernate_testAU")
but when I try to create the schema, I get a HibernateException (The specified schema name "nhibernate_testAU" either does not exist or you do not have permission to use it.)
for what it's worth, my backend is SQL Server 2005

In addition to actually creating the database, I specified the schema to "dbo".
c.SetEnversProperty(ConfigurationKey.DefaultSchema, "dbo");
c.SetEnversProperty(ConfigurationKey.DefaultCatalog, "MyCatalog_Audit");
Also, I have my own RevistionEntity class, so, I needed to add the catalog and schema to my hbm.
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MyAssembly" namespace="MyNamespace">
<class name="MyRevisionEntity" table="REVINFO" catalog="MyCatalog_Audit" schema="dbo">
<id name="Id" column="MyRevisionEntityId">
<generator class="identity"/>
</id>
<property name="AuditDate"></property>
<property name="UserName"></property>
<!--modifiedEntityNames-->
<set name="ModifiedEntityNames" table="REVCHANGES" catalog="MyCatalog_Audit" schema="dbo">
<key column="REV"/>
<element column="ENTITYNAME" type="string"/>
</set>
</class>
</hibernate-mapping>
HTH
Chuck

You need to manually create the catalog/database. AFAIK - NH's SchemaExport don't create database/catalog (or schemas) for you.

Related

Why is NHibernate not returning any data?

I am having some problem configuring NHibernate to retrieve data in my MVC 4 application.
To keep things simple I have configured all code in the Index method.
Here is code for my Category controller :
and here is my configuration in web.config :
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory name="NHibernate.Test">
<property name="connection.driver_class">
NHibernate.Driver.SqlClientDriver
</property>
<property name="connection.connection_string">
Data Source=.;Initial Catalog=UsingNH;uid=myuid;Password=mypwd
</property>
<property name="adonet.batch_size">10</property>
<property name="show_sql">true</property>
<property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
<property name="use_outer_join">true</property>
<property name="command_timeout">60</property>
<property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>
<property name="proxyfactory.factory_class">
NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu
</property>
</session-factory>
</hibernate-configuration>
Mapping file for Category is
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="nhibernate-mapping-2.2" namespace="UsingNHibernate.Models" assembly="UsingNHibernate">
<class name="Category" table="Categories" lazy="false">
<id name="Id" columnId="Id" unsaved-value="0">
<generator class="native" />
</id>
<property name="Name">
<column name="Name" data-type="varchar(50)" not-null="true" />
</property>
</class>
</hibernate-mapping>
and the Category table schema is
CREATE TABLE [dbo].[Categories](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_Category] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
) ON [PRIMARY]
The problem is that the program compiles and runs well but does not return any category.
The code
var lst = (List<Category>)criterion.List<Category>();
returns 0 items (verified in debugger).
Is there any problem in my configuration or Mapping files?
Comment if additional info is required.
Thanks.
If no mappings are defined, nhibernate will simply fail silently and return an empty list if you query a list of entities.
I guess you do not copy over the mapping files to your bin directory. Mark the mapping files to be copied (via properties).
I changed the Build Action Property of the hbm mapping file to Embedded Resource,
then I can get the data.
(It's same way as the OP's comment, but I post it as an answer to be easier noticed.)

Need help with simple NHibernate mapping

Need help with a simple NHibernate relationship...
Tables/Classes
Request
-------
RequestId
Title
…
Keywords
-------
RequestID (key)
Keyword (key)
Request mapping file
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="CR.Model" assembly="CR">
<class name="CR.Model.Request, CR table="[dbo].[Request]" lazy="true">
<id name="Id" column="[RequestID]">
<generator class="native" />
</id>
<property name="RequestorID" column="[RequestorID]" />
<property name="RequestorOther" column="[RequestorOther]" />
…
Keyword??
</class>
</hibernate-mapping>
How do I simply map multiple keywords to a request? I don't need another mapping file for the keyword class, do I?
It's be great if I could not only get the associated keywords, but add them too...
You'll need a set (or some other kind of collection mapping, but I think a set is the best-fit).
check this

NHibernate - No Class Mappings

Why don't I have any class mappings after calling Configuration.Configure()?
Here is my class mapping file Category.hbm.xml for BudgetModel.Category:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="BudgetModel" namespace="BudgetModel">
<class name="Category" table="Categories">
<id name="Id" type="Int32">
<generator class="native" />
</id>
<property name="Name" type="string" not-null="true" />
</class>
</hibernate-mapping>
EDIT
NH version is 2.1.1.GA
Category.hbm.xml is an embedded resource & I have rebuilt.
You need to tell NHibernate where your mapping files are. You normally do this either programmatically or in the configuration file.
config.AddAssembly(typeof(Category).Assembly);
or
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<!--Configuration Properties-->
<mapping assembly="BudgetModel" />
</session-factory>
</hibernate-configuration>
Also, your hibernate mapping file must be set with a build action of embedded resource.

NHibernate mapping of lookup collection (if that makes any sense)

I'm not sure how to ask the question, for I don't know what I don't know, and therefore I don't know the proper terminology for what I'm trying to get the answer to. I will explain my scenario, in hopes that it will help:
I've got three tables, a Book table, a Tag table and a BookTag lookup table.
Each book has an ID, a Title (for starters)
Each tag has an ID, and a Title
Each BookTag has an ID, a BookID, and a TagID.
A book can be tagged with multiple tags, and a tag can be used on more than one BookID.
I've got my objects setup in this fashion:
Book.cs
int BookID
string Title
List<BookTag> Tags
Tag.cs
int TagID
string Title
BookTag.cs
int ID
int BookID
int TagID
I would like the Books.cs class to have a collection of Tags, and not BookTags, but I cannot seem to get the mapping right in NHibernate. This is what I've got for the Book.hbm.xml file:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="DomainModel" namespace="DomainModel.Books">
<class name="DomainModel.Books.Book" table="Books">
<id name="BookID" type="Int32" unsaved-value="0">
<generator class="native"/>
</id>
<property name="Title" type="String" not-null="true"/>
<set lazy="true" name="Tags" table="BookTags" generic="true" inverse="true" cascade="delete">
<key column="BookID"/>
<one-to-many class="DomainModel.Books.BookTag, DomainModel"/>
</set>
</class>
</hibernate-mapping>
And this is my BookTag.hbm.xml:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="DomainModel" namespace="DomainModel.Books">
<class name="DomainModel.Books.BookTag" table="BookTags">
<id column="BookTagID" name="BookTagID" type="Int32" unsaved-value="0">
<generator class="native"/>
</id>
<many-to-one name="Tag">
<column not-null="true" name="TagID"/>
</many-to-one>
<many-to-one name="Book">
<column not-null="true" name="BookID"/>
</many-to-one>
</class>
</hibernate-mapping>
Under this model, I can get to the tag I want by using my object model: Book.Tags[0].Tag, but that just seems inefficient. Can I use NHibernate to map out the BookTags.TagID with the Tags.TagID in the database so that I can get Book.Tags[0] to return a Tag object, instead of a BookTags object? I didn't know of a better way to associate Books to tags so that a tag used on Book1 can be used on Book2 without adding a new entry to the Tags table.
I hope this makes at least some sense. Let me know if you need further clarification. I'll post my solution here if I figure it out before someone answers.
You don't need a BookTag class at all. You can map Book.Tags collection as many-to-many. To do this you will specify BookTag in the map to connect the association. Look here in section 6.8 Bidirectional Associations.
Thank you Tim, that was what I needed. For those that are curious, I "un-mapped" the BookTag table/objects, and now just have a Book object and a Tag object that are used and mapped to NHibernate.
My Book.hbm.xml was updated to this:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="DomainModel" namespace="DomainModel.Books">
<class name="DomainModel.Books.Book" table="Books">
<id name="BookID" type="Int32" unsaved-value="0">
<generator class="native"/>
</id>
<property name="Title" type="String" not-null="true"/>
<bag name="Tags" table="BookTag" generic="true">
<key column="BookID" on-delete="noaction"></key>
<many-to-many class="Tag" column="TagID"></many-to-many>
</bag>
</class>
</hibernate-mapping>

How to use a child object field as part of the compound key in another child in NHibernate

I need to create a new Many-To-One relationship on my User entity which joins against another entity. The problem is the other entity has a compound key of which 1 field is a field in the User entity and the other is a field in another Many-To-One entity.
User.Key -> User.NewThing.Key
User.SubThing.Key -> User.NewThing.Key
Below is the invalid mapping file I am ideally wanting to use where JeanieUserTyped is my newthing and the ApplicationId is the key in question which comes from ShortCode.ApplicationId.
Question is how do I tell it to map the application part of the compound key?
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="JeanieMaster.Domain.Entities" assembly="JeanieMaster.Domain">
<class name="JeanieUser" table="DBSVR1.Jeanie_Master.dbo.JeanieUser" select-before-update="false" optimistic-lock="none">
<id name="Id" column="UserId" type="Int32">
<generator class="identity"/>
</id>
<property name="Mobile" type="String"/>
<property name="UniqueReoccurBillingRefId" type="String"/>
<property name="DateJoined" type="DateTime"/>
<property name="IsActive" type="Boolean"/>
<many-to-one name="MobileNetwork" class="MobileNetwork" column="MobileNetworkId" />
<many-to-one name="ShortCode" class="ShortCode" column="ShortCodeId" />
<many-to-one name="MobileHandset" class="MobileHandset" column="HandsetId" />
<many-to-one name="JeanieUserTyped" class="JeanieUserTyped">
<column name="Mobile" />
<column name="ApplicationId" />
</many-to-one>
</class>
</hibernate-mapping>
Can you give more details, sounds like you have 3 entities,
User
SubThing
NewThing
Where NewThing resolves a Many-to-Many with User and SubThing - am I close?
Maybe like this:
User -< SubThing
| |
/\ /\
NewThing
I don't suppose the composite key stuff in nhibernate is relevant?

Categories

Resources