1

私はこのマッピングを定義しました:

public class Mapping : ConventionModelMapper
{
    public Mapping()
    {
        IsRootEntity((type, declared) =>
                         {
                             return !type.IsAbstract &&
                                    new[] { typeof(Entity<Guid>), typeof(CommonEntity) }.Contains(type.BaseType);
                         });

        IsEntity((x, y) => typeof(Entity<Guid>).IsAssignableFrom(x) && !x.IsAbstract && !x.IsInterface);

        IsSet((mi, wasDeclared) =>
                  {
                      var propertyType = mi.GetPropertyOrFieldType();
                      return propertyType.IsGenericType && typeof(System.Collections.Generic.ISet<>).IsAssignableFrom(propertyType.GetGenericTypeDefinition());
                  });

        IsManyToMany((mi, wasDeclared) =>
                         {
                             var propertyType = mi.GetPropertyOrFieldType();
                             var containingType = mi.ReflectedType;

                             if (typeof(System.Collections.Generic.ISet<>).IsAssignableFrom(propertyType.GetGenericTypeDefinition()))
                             {
                                 var referenceType = propertyType.GetGenericArguments()[0];
                                 return true;
                                 return !referenceType.GetProperties(BindingFlags.Instance | BindingFlags.Public).Any(p => p.PropertyType.IsAssignableFrom(containingType));
                             }
                             return false;
                         });

        Class<Entity<Guid>>(x =>
                                {
                                    x.Id(c => c.Id, m => m.Generator(Generators.GuidComb));
                                    x.Version(c => c.Version, (vm) => { });
                                });

        BeforeMapClass += OnBeforeMapClass;
        BeforeMapManyToOne += OnBeforeMapManyToOne;
        BeforeMapSet += OnBeforeMapSet;
        BeforeMapManyToMany += OnBeforeMapManyToMany;

        Class<CommonEntity>(x =>
        {
            x.Property(c => c.DateCreated, m => m.Type<UtcDateTimeType>());
            x.Property(c => c.DateModified, m => m.Type<UtcDateTimeType>());
        });
    }

    private void OnBeforeMapManyToMany(IModelInspector modelInspector, PropertyPath member, IManyToManyMapper collectionRelationManyToManyCustomizer)
    {
        collectionRelationManyToManyCustomizer.Column(member.LocalMember.GetPropertyOrFieldType().GetGenericArguments()[0].Name + "Id");
    }

    private void OnBeforeMapSet(IModelInspector modelInspector, PropertyPath member, ISetPropertiesMapper propertyCustomizer)
    {
        propertyCustomizer.Key(k=>k.Column(member.GetContainerEntity(modelInspector).Name + "Id"));
        propertyCustomizer.Cascade(Cascade.Persist);
        if (modelInspector.IsManyToMany(member.LocalMember))
        {
            propertyCustomizer.Table(member.GetContainerEntity(modelInspector).Name +
                                     member.LocalMember.GetPropertyOrFieldType().GetGenericArguments()[0].Name);
        }
    }

    private void OnBeforeMapManyToOne(IModelInspector modelInspector, PropertyPath member, IManyToOneMapper propertyCustomizer)
    {
        propertyCustomizer.Column(member.LocalMember.Name + "Id");
    }

    private void OnBeforeMapClass(IModelInspector modelInspector, Type type, IClassAttributesMapper classCustomizer)
    {
        classCustomizer.Table('['+ type.Name + ']');
    }
}

私は多対多の関係に問題を抱えています。User、UserPermission、およびPermissionがあります。パーミッションをアタッチした後でユーザーを保存すると、次のSQLが生成されます。

exec sp_executesql N'UPDATE [Permission] SET UserId = @p0 WHERE Id = @p1',N'@p0 uniqueidentifier,@p1 uniqueidentifier',@p0='57A2CD87-4A79-4131-B9CE-A1060168D520',@p1='9D99D340-1B63-4291-B55A-6127A8F34FC9'

次のようになります。

exec sp_executesql N'INSERT INTO UserPermission (UserId, PermissionId) VALUES (@p0, @p1)',N'@p0 uniqueidentifier,@p1 uniqueidentifier',@p0='2C670A01-C2E6-46A3-A412-A1060168F976',@p1='9D99D340-1B63-4291-B55A-6127A8F34FC9'

ユーザーに特定のクラスマッピングを追加すると、次のようになります。

        Class<User>(classMapper =>
                        {
                            classMapper.Set(x => x.Permissions, map =>
                                                        {
                                                            //map.Key(k => k.Column("UserId"));
                                                            //map.Table("UserPermission");
                                                        }, r => r.ManyToMany(m => {}));
                        });

キーとテーブルの定義を省略して、列を呼び出さずに多対多を含めることができ、機能します。しかし、それは私のBeforeManyToManyイベントハンドラーと同じことをします。クラス全体を削除すると、BeforeMapManyToManyイベントは発生せず、nHibernateはPermissionテーブルにUserIdがあると見なします。

Heresユーザー:

public class User : CommonEntity
{
    protected User()
    {
        Permissions = new HashSet<Permission>();
    }

    public User(User createdBy) : base(createdBy)
    {
        Permissions = new HashSet<Permission>();
    }

    public ISet<Permission> Permissions { get; protected set; }
}
4

1 に答える 1

2

ソースコードを調べた後、IsManyToManyの前にセットを定義するときに、IsOneToManyがプロパティに対してチェックされるという問題があることに気付きました。IsOneToManyを定義する必要があり、明示的なマッピングなしで機能しました。

        IsOneToMany((mi, wasDeclared) =>
        {
            var propertyType = mi.GetPropertyOrFieldType();

            return ModelInspector.IsEntity(propertyType);
        });
于 2012-11-12T09:06:31.483 に答える