我已经定义了这个映射:
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 + ']');
}
}
我遇到了多对多关系的问题。我有用户、用户权限和权限。当我在附加权限后保存用户时,它会生成以下 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 => {}));
});
我可以省略键和表定义,并在没有列调用的情况下包含 ManyToMany,它可以工作。但它与我的 BeforeManyToMany 事件处理程序做同样的事情。如果我放弃整个 Class 事件,则不会触发 BeforeMapManyToMany 事件,并且 nHibernate 认为我的 Permission 表上有一个 UserId。
继承人用户:
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; }
}