Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problems with generated SQL #167

Open
lakario opened this issue Sep 17, 2012 · 3 comments
Open

Problems with generated SQL #167

lakario opened this issue Sep 17, 2012 · 3 comments

Comments

@lakario
Copy link

lakario commented Sep 17, 2012

I'm having a bit of trouble with some SQL generated by my FluentNHibernate mappings. I'm not doing anything too complex, but unfortunately it's not behaving the way I would have expected.

I have a table-per-type hierarchy relating a ContentModule table to several sub-type tables. For the CategoryContentModule and EventContentModule types, there is an additional one-to-many relationship to the ContentItem table.

Mapping

Here's the class definition for my tables; make note of the intermediary abstract type ContentItemContentModule:

public abstract class ContentModule
{
    public virtual string Name { get; set; }
    public virtual ModuleStatus Status { get; set; }
    public virtual DateTime? ExpirationDateTime { get; set; }
    public virtual DateTime? LastPublishedDateTime { get; set; }
    public virtual DateTime? LastUnpublishedDateTime { get; set; }
}

public class CustomContentModule : ContentModule
{
    public virtual string ViewPath { get; set; }
}

public abstract class ContentItemContentModule : ContentModule
{
    public virtual ContentItem ContentItem { get; set; }
}

public class EventContentModule : ContentItemContentModule
{
    public virtual Event Event { get; set; }
}

public class CategoryContentModule : ContentItemContentModule
{
    public virtual Category Category { get; set; }
}

Finally, my mappings:

public class ContentModuleMapping : ClassMap<ContentModule>
{
    public ContentModuleMapping()
    {
        Map(x => x.Name);
        Map(x => x.Status).CustomType<ContentModule.ModuleStatus>();
        Map(x => x.ExpirationDateTime);
        Map(x => x.LastPublishedDateTime);
        Map(x => x.LastUnpublishedDateTime);
    }
}

public class CustomContentModuleMapping : SubclassMap<CustomContentModule>
{
    public CustomContentModuleMapping()
    {
        Map(x => x.ViewPath).Not.Nullable();
    }
}

public class EventContentModuleMapping : SubclassMap<EventContentModule>
{
    public EventContentModuleMapping()
    {
        References(x => x.ContentItem).Nullable().Cascade.None();
        References(x => x.Event).Not.Nullable().LazyLoad().Cascade.None();
    }
}

public class CategoryContentModuleMapping : SubclassMap<CategoryContentModule>
{
    public CategoryContentModuleMapping()
    {
        References(x => x.ContentItem).Nullable().Cascade.None();
        References(x => x.Category).Not.Nullable().LazyLoad().Cascade.None();
    }
}

As you can see, the intermediary type ContentItemContentModule is never mapped and exists only to provide the ContentItem property of its sub-types. In the mappings for each sub-type I explicitly map the ContentItem property.


When this mapping is registered and I attempt to retrieve a collection of ContentModule items via NHibernate, the generated SQL produces a non-existent column called ContentItemContentModuleId.

I've attempted explicitly setting the column name of the ContentItem reference to 'ContentItemId' (matching the table structure), but this did not work. After some experimentation I determined that referencing the ContentItem property was not the problem, but rather having the intermediary class ContentItemContentModule was. If I remove the intermediary abstract class and move the ContentItem property into each sub-type, the SQL is generated correctly and everything works.

The solution I came up with was simply to eliminate the intermediary abstract type and instead use an interface to achieve the same result in my code, but this is obviously a workaround.


TL;DR For some reason, FluentNHibernate is having problems with there being an unmapped abstract type between a mapped base abstract type and a mapped concrete type in a table-per-type hierarchy.

@chester89
Copy link
Collaborator

I'm not an expert in mapping inheritance hierarchies, but if you use table-per-type, shouldn't all types in hierarchy be mapped, including abstract ones? Although I'm not sure what's Fluent default behaviour in this particular case

@lakario
Copy link
Author

lakario commented Sep 18, 2012

@chester89 While I do not disagree, the intermediary type is not intended to have its own table and if I map it, FluentNHibernate will assume that it does.

@chester89
Copy link
Collaborator

can you post generated hbm files for this? It just got to me that errors in SQL may have to do with NHibernate

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants