以聪明的方式映射IDictionary<string, class> 的Fluent NHibernate映射

5

给定以下类:

using System.Collections.Generic;

namespace FluentMappingsQuestion
{
    public class Entity
    {
        public virtual int Id { get; set; }
        public virtual IDictionary<string, Property> Properties { get; set; }
    }

    public class Property
    {
        public virtual Entity OwningEntity { get; set; }
        public virtual string Name { get; set; }
        public virtual int Value { get; set; }
        public virtual decimal OtherValue { get; set; }
    }
}

我该如何使用NHibernate(最好是流畅的风格)来映射它们,以便能够实现以下操作:

[Test]
public void EntityPropertyMappingTest()
{
    using (var session = _factory.OpenSession())
    {
        var entity = new Entity();

        // (#1) I would *really* like to use this
        entity.Properties["foo"] = new Property { Value = 42, OtherValue = 42.0M };

        session.Save(entity);
        session.Flush();

        // (#2) I would like the entity below to "update itself"
        // on .Save or .Flush. I got it to work with .Load()
        Assert.AreEqual(42, entity.Properties["foo"].Value);
        Assert.AreEqual(42.0M, entity.Properties["foo"].OtherValue);
        Assert.AreEqual("foo", entity.Properties["foo"].Name);
        Assert.AreEqual(entity, entity.Properties["foo"].Owner);
    }
}

我几乎已经通过以下映射来完成了这个:

// class EntityMap : ClassMap<Entity>
public EntityMap()
{
    Id(x => x.Id);
    HasMany(x => x.Properties)
    .Cascade.AllDeleteOrphan()
    .KeyColumn("EntityId")
    .AsMap(x => x.Name);
}

// class PropertyMap : ClassMap<Property>
public PropertyMap()
{
    Id(x => x.Id);
    References(x => x.OwningEntity).Column("EntityId");
    Map(x => x.Name).Length(32);
    Map(x => x.Value);
{

我所遇到的问题:
  • 如果我使用Entity.Properties .Inverse(),会出现错误
  • 如果我不使用.Inverse(),NHibernate会执行INSERT(Entity), INSERT(Property), UPDATE(Property)而不是只有INSERT(Entity), INSERT(Property)
  • 如果我把Property.Name.Not.Nullable()属性设置为非空,也会出现错误
  • 如果我不使用.Not.Nullable(),数据库模式中就会有一个空缺
我应该如何更改我的映射?

如果你真的想使用这样的代码:entity.Properties["foo"] = 42;那么你为什么要创建这个Property类呢?为什么不像通常一样使用IDictionary<string,int>,然后将其映射为NHibernate映射呢? - Paul Batum
@Paul: 理想情况下,我希望能够将其与类和继承一起使用。我粘贴的代码示例在这方面似乎有点不清楚。我会更新它的。 - Marcin Seredynski
1个回答

4

我解决了这个问题,通过指定以下映射:

HasMany<Property>(Reveal.Member<Entity>("InternalProperties"))
  .AsMap(p => p.Name)
  .Cascade.AllDeleteOrphan()
  .Inverse();

创建两个类型为IDictionary<string, Property>的属性:PropertiesInternalProperties。第一个属性是第二个属性的代理字典,并处理为Property条目设置OwningEntityName属性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接