我正在尝试使用代码映射配置具有自定义/动态字段的实体。我基于这两篇文章中的以下代码:
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=?
数据库的架构如下:
关于如何让NHibernate从正确的表中选择自定义/动态字段的任何想法?
对此做了一些进一步的研究,看起来这可能是原因:
https://nhibernate.jira.com/browse/NH-3198
此外,转储生成的XML我们得到:
请注意&lt; dynamic-component&gt;不是&lt; join&gt;。
的子元素答案 0 :(得分:0)
在修复此问题之前,您可以下载源代码,并进行这些更改以使代码正常运行:
IJoinMapper
而不是:
public interface IJoinMapper : IJoinAttributesMapper
, ICollectionPropertiesContainerMapper
, IBasePlainPropertyContainerMapper { }
我们需要像这样定义:
public interface IJoinMapper : IJoinAttributesMapper, IPropertyContainerMapper { }
我们需要这个新的覆盖
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);
}
...
方法: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