动态字段和代码映射

时间:2014-10-23 12:18:36

标签: nhibernate mapping-by-code

我正在尝试使用代码映射配置具有自定义/动态字段的实体。我基于这两篇文章中的以下代码:

http://ayende.com/blog/4776/support-dynamic-fields-with-nhibernate-and-net-4-0 http://notherdev.blogspot.co.uk/2012/01/mapping-by-code-dynamic-component.html

Customer实体定义如下:

public class Customer
{
    public virtual Guid Id { get; protected set; }
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
    public virtual DateTime Created { get; set; }
    public virtual IDictionary<string, object> Attributes  { get; protected set; }

    protected Customer()
    {
        this.Attributes = new Dictionary<string, object>();
    }
}

,映射定义为:

    public class Mapping : ClassMapping<Customer>
    {
        public Mapping()
        {
            Table("Customers");

            Id(x => x.Id, id =>
            {
                id.Column("Id");
                id.Generator(Generators.GuidComb);
            });

            Property(x => x.FirstName);
            Property(x => x.LastName);
            Property(x => x.Created);

            Join("CustomerAttributes", x =>
                {
                    x.Table("CustomerAttributes");
                    x.Key(k => k.Column("CustomerId"));
                    x.Optional(false);
                    x.Fetch(FetchKind.Join);
                    x.Component("Attributes", new 
                        {
                            HasChildren = 0
                        },
                        m =>
                        {
                            m.Property(p => p.HasChildren);
                        });
                });
        }
    }

我认为我接近它正在运行,但我遇到的问题是,当我检索客户时,生成的SQL无效。它正在Customers表上查找HasChildren字段而不是CustomerAttributes表。它生成的SQL是:

SELECT customer0_.Id as Id1_0_, customer0_.FirstName as FirstName1_0_, customer0_.LastName as LastName1_0_, customer0_.Created as Created1_0_, customer0_.HasChildren as HasChild5_1_0_ FROM Customers customer0_ inner join CustomerAttributes customer0_1_ on customer0_.Id=customer0_1_.CustomerId WHERE customer0_.Id=?

数据库的架构如下:

schema diagram

关于如何让NHibernate从正确的表中选择自定义/动态字段的任何想法?

对此做了一些进一步的研究,看起来这可能是原因:

https://nhibernate.jira.com/browse/NH-3198

此外,转储生成的XML我们得到:

enter image description here

请注意&lt; dynamic-component&gt;不是&lt; join&gt;。

的子元素

1 个答案:

答案 0 :(得分:0)

在修复此问题之前,您可以下载源代码,并进行这些更改以使代码正常运行:

1)IJoinMapper

而不是:

public interface IJoinMapper : IJoinAttributesMapper
      , ICollectionPropertiesContainerMapper
      , IBasePlainPropertyContainerMapper { }

我们需要像这样定义:

public interface IJoinMapper : IJoinAttributesMapper, IPropertyContainerMapper { }

2)JoinCustomizer

我们需要这个新的覆盖

public class JoinCustomizer<TEntity> : PropertyContainerCustomizer<TEntity>, IJoinMapper<TEntity>
    where TEntity : class
{
    protected override void RegisterDynamicComponentMapping<TComponent>(Expression<Func<TEntity, System.Collections.IDictionary>> property
        , Action<IDynamicComponentMapper<TComponent>> mapping)
    {
        MemberInfo member = TypeExtensions.DecodeMemberAccessExpression(property);
        ExplicitDeclarationsHolder.AddAsPropertySplit(new SplitDefinition(typeof(TEntity), splitGroupId, member));
        base.RegisterDynamicComponentMapping(property, mapping);
    }
   ...

3)ModelMapper

方法:MapSplitProperties的{​​{1}}需要多一个ModelMaper语句

else if

这将是新方法def:

else if (modelInspector.IsDynamicComponent(member))
{
    MapDynamicComponent(member, memberPath, propertyType, propertiesContainer);
}

这些变化应该是上述问题。我还将这些行传递给NH issue log

此处还创建了一个拉取请求:https://github.com/nhibernate/nhibernate-core/pull/366