Nhibernate Evers, how to change AuditJoinTable name - nhibernate

i'am using fluent Nhibernate and Envers with this setup
var enversConf = new NHibernate.Envers.Configuration.Fluent.FluentConfiguration();
enversConf.Audit<Segnalazione>()
IRevisionListener revListner = services.GetService<IRevisionListener>();
enversConf.SetRevisionEntity<RevisionEntity>(e => e.Id, e => e.RevisionDate, revListner);
cfg.SetEnversProperty(ConfigurationKey.AuditTableSuffix, "_LOG");
cfg.SetEnversProperty(ConfigurationKey.AuditStrategy, typeof(CustomValidityAuditStrategy));
cfg.IntegrateWithEnvers(enversConf);
i need to change AuditJoinTable naming adding a prefix XXX_
All others table have same prefix and so standard logging table inherits it, only JoinTable hasn't it
i found settings for java version but not for .net one
EDIT:
Now i have table with this naming convention:
XXX_Table1
XXX_Table2
main log table are create with _LOG suffix, so i get
XXX_Table1_LOG
XXX_Table2_LOG
while
AuditJoinTable are created as
Table1Table2_LOG
and i need
XXX_Table1Table2_LOG

I am solving this by adding the name to each join table. Could be more generic but it works.
enversConf.Audit<Segnalazione>()
.SetTableInfo(ug => ug.Foo, t => t.TableName = "XXX_Segnalazione_Foo")

Do you mean that cfg.SetEnversProperty(ConfigurationKey.AuditTablePrefix, "XXX_") doesn't work? It should.
IEnversNamingStrategy is used to decide names for tables, default this one is used where ConfigurationKey.AuditTablePrefix is used for "default prefix". You can also inject your own impl of this interface if you want to.
Using SetTableInfo overrides this and surely works but if I understand you correctly you don't need to do that in this case.

Related

ContentHandler issues (circular reference) in Orchard

crosspost: https://orchard.codeplex.com/discussions/459007
First question I have is what would be the repercussions of having 2 PartHandlers for the same Part in 2 different modules?
I got into this predicament because I have to run a method once a specific Content Type is created. It would be as easy to hook onto OnCreated for the part, however, here is my scenario:
Module A contains the part and the original handler
Module B contains the service where the method is
Module B has a reference to Module A
Therefore, I am unable to reference Module B within Module A (circular reference). So what I did was to copy the exact same PartHandler in Module A and placed it in Module B.
Would anything be wrong with that?
Then comes my second question, which I think could solve all these problems: Can we create a PartHandler for the Content Item's default Content Part? (i.e. the part where all custom fields are attached to)
This would definately make things easier as I could consolidate stuff that need to run there.
UPDATE 1 (to better explain question 2)
ContentDefinitionManager.AlterPartDefinition("EventItem",
builder => builder
.WithField("StartDate", cfg => cfg
.OfType("DateTimeField")
.WithDisplayName("Start Date")
.WithSetting("DateTimeFieldSettings.Display", "DateOnly")
.WithSetting("DateTimeFieldSettings.Required", "true"))
.WithField("StartTime", cfg => cfg
.OfType("DateTimeField")
.WithDisplayName("Start Time")
.WithSetting("DateTimeFieldSettings.Display", "TimeOnly"))
.WithField("EndDate", cfg => cfg
.OfType("DateTimeField")
.WithDisplayName("End Date")
.WithSetting("DateTimeFieldSettings.Display", "DateOnly"))
.WithField("EndTime", cfg => cfg
.OfType("DateTimeField")
.WithDisplayName("End Time")
.WithSetting("DateTimeFieldSettings.Display", "TimeOnly"))
.WithField("Intro", cfg => cfg
.OfType("TextField")
.WithDisplayName("Intro")
.WithSetting("TextFieldSettings.Flavor", "textarea"))
ContentDefinitionManager.AlterTypeDefinition(
"EventItem"
, cfg =>
cfg
.DisplayedAs("Event Item")
.WithPart("TitlePart")
.WithPart("EventItem")
.WithPart("LocationPart")
.WithPart("AutoroutePart", builder => builder
.WithSetting("AutorouteSettings.AllowCustomPattern", "true")
.WithSetting("AutorouteSettings.AutomaticAdjustmentOnEdit", "false")
.WithSetting("AutorouteSettings.PatternDefinitions", "[{Name:'Title', Pattern: 'learn/events/{Content.Slug}', Description: 'learn/events/event-title'}]")
.WithSetting("AutorouteSettings.DefaultPatternIndex", "0"))
.WithPart("CommonPart")
.Draftable()
.Creatable()
);
I'm talking about creating a ContentHandler for the EventItem part which holds all the custom fields. How can I go about it when EventItemPart is not defined in any class in the solution?
The following below won't work since it can't find the class EventItemPart:
OnCreated<EventItemPart>((context, keynotes) =>
questionService.SetDefaultQuestions(context.ContentItem));
Cross-answer as well.
Bertrand's perfectly right. Why do you need to reference B in A in first place? If the service from B needs A and A needs this service, then it belongs to A (at least the interface - contract).
You can always split interface and actual implementation for your service, having one in different module than another. If implementation of your service requires stuff from B, then put the interface in A, but actual implementation in B. This way A doesn't even need to know about the existence of B, but still be able to use the service via it's interface - it's the beauty of IoC pattern and Orchard modularity:)
You may use ContentPart or IContent as a type argument in handler generic methods. It's perfectly valid. This way you'd be able to plug in to events on all items, and perform custom filtering afterwards (based on type name, some field existence etc.). In your case it may look like:
OnCreated<ContentPart>((context, part) =>
{
if(part.ContentItem.ContentType != "EventItem") return;
questionService.SetDefaultQuestions(context.ContentItem);
});
Update: no need to do this: .WithPart("EventItem"). This 'fake' part will be automatically added by framework.
Cross-answer:
none
However, repeating yourself is almost always wrong, especially if it's done for a bad reason. Why is are the service and the part in two different modules? Why does A need B? A circular reference indicates tight coupling. If the tight coupling is justified, then it should happen in a single module. If it's not, then you need to re-do your design to remove it.
You can create a handler for anything, but your explanation of your scenario is way to vague and abstract to give any useful advice.

SQLite DB built from fluent nhibernate description produces columns that are not nullable

I have the following code to create an in-memory SQLite DB for testing:
Configuration config = null;
FluentConfiguration fluentConfiguration = Fluently.Configure().Database(SQLiteConfiguration.Standard.InMemory().ShowSql()
).Mappings(m =>
{
m.FluentMappings.AddFromAssemblyOf<ReturnSourceMap>();
m.HbmMappings.AddFromAssemblyOf<ReturnSourceMap>();
m.FluentMappings.AddFromAssemblyOf<EchoTransaction>();
}).ExposeConfiguration(c => config = c);
ISessionFactory sessionFactory = fluentConfiguration.BuildSessionFactory();
_session = sessionFactory.OpenSession();
new SchemaExport(config).Execute(true, true, false, _session.Connection, Console.Out);
which seems to work fine for most things but unfortunately it is creating all the columns as not nullable.
For instance I have two classes:
InternalFund and ExternalFund. Both inherit from Fund and both persist to the same table.
ExternalFund has a column Manager_ID, InternalFund doesn't. Unfortunately this means that I can't persist an InternalFund as it throws a SQL Exception.
I don't need the referential integrity for my tests so would be happy if I could just make all columns nullable.
Does anyone know how to do this?
Thanks
Stu
You should try using the FluentNhibernate feature of Conventions. If you check out this link you will see the first example is of setting nullability as a default.
Oops, terribly sorry. It seems that the SQLite DB assumes nullability unless otherwise stated - unlike TSQL which requires it in the create statement.
In fact, I found hidden away in a sub-method that the particular property had a not null set on it in the mapping. Removing this sorted the problem.
Thanks for posting about conventions though, I'll have a look as I have another issue that they might sort.
Cheers
Stu

How to set database schema for namespace in nhibernate

I have a database with multiple schemas: Security, Trade, etc.
Each shema has multiple tables. Ie. Security schema has: Users, Roles etc..
Now, can I setup nhibernate so that the schema i bound to namespace.
Ie. I have a security namespace in my project with the User and Role POCOs in it.
So I wont to set bind database schema to namespace.
I know i can add Schema in maping file for each class, but if I have ie. 1000 class i must specify schema for each clas.
Please help.
you can do what you want programatically right before you create your sessionfactory like this:
var cfg = new Configuration().Configure();
foreach (var pc in cfg.ClassMappings)
{//just an example
pc.Table.Schema = pc.MappedClass.Assembly.GetName().FullName.Substring(0, 3);
}
var sessionFactory = cfg.BuildSessionFactory();
note that normally you only build your session factory once so the performance impact (if any) happens only once.
NHibernate won't do it magically. If you want to avoid changing mapping files manually, use a code-based solution like ConfORM or FluentNHibernate instead.

NHibernate: How to get mapped values?

Suppose I have a class Customer that is mapped to the database and everything is a-ok.
Now suppose that I want to retrieve - in my application - the column name that NH knows Customer.FirstName maps to.
How would I do this?
You can access the database field name through NHibernate.Cfg.Configuration:
// cfg is NHibernate.Cfg.Configuration
// You will have to provide the complete namespace for Customer
var persistentClass = cfg.GetClassMapping(typeof(Customer));
var property = persistentClass.GetProperty("FirstName");
var columnIterator = property.ColumnIterator;
The ColumnIterator property returns IEnumerable<NHibernate.Mapping.ISelectable>. In almost all cases properties are mapped to a single column so the column name can be found using property.ColumnInterator.ElementAt(0).Text.
I'm not aware that that's doable.
I believe your best bet would be to use .xml files to do the mapping, package them together with the application and read the contents at runtime. I am not aware of an API which allows you to query hibernate annotations (pardon the Java lingo) at runtime, and that's what you would need.
Update:
Judging by Jamie's solution, NHibernate and Hibernate have different APIs, because the Hibernate org.hibernate.Hibernate class provides no way to access a "configuration" property.

NHibernate - Incorrect thinking? Subclassed Model based on Join

I have a simple model class (Part), which pulls from it's information from a single table (t_Part).
I would like a subclass of this model called (ProducedPart), that would still utilize NHibernate's caching mechanisms, but would only be instances of (Part) that have a foreign key relationship in a table called "t_PartProduction". I do not need to have a model for this second table.
I only need a read-only version of ProducedPart
I could always implement a Facade/Repository over this, but I was hoping to setup a mapping that would pull "t_Part" joined with "PartProduction" when I asked for "ProducedPart" in NH.
Is this the wrong way to use NH?
Edit
So, the SQL would look something like
SELECT p.*
FROM t_Part p
INNER JOIN t_PartProduction pp ON pp.PartID = p.PartID
WHERE pp.ProductionYear = '2009'
I believe what you are looking for is a joined subclass. In FNH, it will look something like:
public class PartMap : ClassMap<Part>
{
public PartMap()
{
Id(x => x.Id)
JoinedSubClass<ProducedPart>("PartID", sub => {
sub.Map(x => x.Name);
sub.Map(x => x.ProductionYear);
});
}
}
In order have NHibernate cache the results, you will need to have the subclass mapped (and if you didn't map it, you wouldn't be able to get NH to load it in the first place).
Bringing in some context from the FNH groups thread, it will not explicitly be read-only though. In my opinion, making things read-only is not an appropriate thing for NHibernate to manage. This is better controlled by the database and connections (i.e. creating a connection to the database that only has SELECT permissions on the tables/views being accessed). See my answer to a previous SO question about readonly sessions in NHibernate for more of my thoughts on the matter.
The key here is using both the where and mutable elements of the class definition for NHibernate Mappings.
Using Fluent NHibernate, this looks like:
public Part()
{
WithTable("t_Part");
Id(i => i.Id).ColumnName("PartID");
Map(m => m.Name).ColumnName("Part");
SetAttribute("where", "PartID IN ( SELECT pp.PartID FROM t_PartProduction pp WHERE pp.ProductionYear = '2009' ) ");
ReadOnly();
}
No, this is perfectly possible. Look in the NHibernate documentation for the "table per subclass" model of inheritance. It will actually implement this as a LEFT JOIN, so that when you load a Part, it creates an instance of either your Part or your ProducedPart class depending on whether the other row is present. You'll find documentation on nhibernate.info.
I'm not sure you could make ProducedPart read-only doing this though.
I'm assuming from this:
WHERE pp.ProductionYear = '2009'
that you want the subclass only where the production year is 2009, i.e. if when there is a record in t_PartProduction for a different year, you want this Part treated as a plain Part object, not a ProducedPart, then you could consider creating a view definition within your database that is a filtered version of t_PartProduction, then making your subclass join to this view rather than the base table.