AutoMapping a Composite Element in Fluent Nhiberna

2019-08-10 13:36发布

问题:

I'm trying to get the AutoPersistence model to map several composite elements. However, it seems that either I end up mapping it as an entity, dropping down to manual mapping or it just doesn't plain work. Here's some code that demonstrates my problem:

using System;
using System.Collections.Generic;
using FluentNHibernate.AutoMap;
using FluentNHibernate.Cfg;
using FluentNHibernate.Conventions.Helpers;
using NHibernate.Cfg;

namespace Scanner {
    public class Root {
        public int Id { get; set; }
        public string Name { get; set; }
        public ICollection<Component> Components { get; set; }
    }

    public class Component {
        public string Name { get; set; }
    }

    class Example {
        public void DoesntGetComponents()
        {
            Configuration configuration = new Configuration();
            configuration.SetProperty("ConnectionString", "");
            configuration.SetProperty("dialect", "NHibernate.Dialect.MsSql2005Dialect");
            var config = Fluently.Configure(configuration)
                .Mappings(m => m.AutoMappings.Add(AutoMapping))
                .BuildConfiguration();
            var sql2005 = new NHibernate.Dialect.MsSql2005Dialect();
            foreach (var line in config.GenerateSchemaCreationScript(sql2005))
            {
                Console.WriteLine(line);
            }
        }

        static AutoPersistenceModel AutoMapping() {
            AutoPersistenceModel model = new AutoPersistenceModel();
            return model
                .AddEntityAssembly(typeof(Root).Assembly)
                .WithSetup(e => e.IsComponentType = t => t == typeof(Component))
                .Where(t => t == typeof(Root))
                .MergeWithAutoMapsFromAssemblyOf<Root>()
                .ConventionDiscovery.Add(ForeignKey.Format((p, t) => (p == null ? t.Name : p.Name) + "Id"))
                .ConventionDiscovery.Add(Table.Is(t => t.EntityType.Name))
            ;
        }
    }
}

(Sorry it's so long, but it's the minimal code required to demonstrate the problem. This particular version of the code fails to register the component type at all.

So, what am I doing wrong?

回答1:

It seems that the component in itself is not the problem, but the mapping of a collection of components. If you would map the component directly onto the Root class, this would not be any problem.

A possible workaround is making the Component class an entity (adding an ID) and overriding the mapping of Components to cascade + auto delete orphans:

AutoPersistenceModel
.ForTypesThatDeriveFrom<Root>(map => map.HasMany(root => root.Components).Cascade.AllDeleteOrphan())