我正在使用Fluent NHibernate为我的应用程序映射一组成员资格类。我正在将类映射到asp.net成员资格数据库结构。与问题相关的数据库模式如下所示:
ASPNET_USERS
UserId PK
ApplicationId FK NOT NULL
other user columns ...
ASPNET_MEMBERSHIP
UserId PK,FK
ApplicationID FK NOT NULL
other membership columns...
这两个表之间存在一对一的关系。我正在尝试将两个表连接在一起,并将两个表中的数据映射到单个“用户”实体,如下所示:
public class User
{
public virtual Guid Id { get; set; }
public virtual Guid ApplicationId { get; set; }
// other properties to be mapped from aspnetuser/membership tables ...
我的映射文件如下:
public class UserMap : ClassMap<User>
{
public UserMap()
{
Table("aspnet_Users");
Id(user => user.Id).Column("UserId").GeneratedBy.GuidComb();
Map(user => user.ApplicationId);
// other user mappings
Join("aspnet_Membership", join => {
join.KeyColumn("UserId");
join.Map(user => user.ApplicationId);
// Map other things from membership to 'User' class
}
}
}
如果我尝试使用上面的代码运行,我会得到一个FluentConfiguration异常
尝试在已添加时添加属性'ApplicationId'。
如果我删除行“Map(user =&gt; user.ApplicationId);”或将其更改为“Map(user =&gt; user.ApplicationId)。 Not.Update()。Not.Insert(); “然后应用程序运行,但在尝试插入新用户时出现以下异常:
无法将值NULL插入“ApplicationId”列,表'ASPNETUsers_Dev.dbo.aspnet_Users';列不允许空值。 INSERT失败。 声明已经终止。
如果我按原样离开 .Map(user =&gt; user.ApplicationId)并对 join <进行其中任何一项更改/strong>.Map(user =&gt; user.ApplicationId)然后我得到相同的异常,当然异常与插入aspnet_Membership表有关
那么......假设我无法更改数据库架构,我该怎么做这种映射?
答案 0 :(得分:4)
我认为我有一些有用的东西。
public class Application
{
public virtual Guid ApplicationId { get; set; }
/* Scalar Properties of an Application */
public virtual string ApplicationName { get; set; }
public virtual string Description { get; set; }
public virtual string LoweredApplicationName
{
get
{
return this.ApplicationName.ToLower();
}
set
{
if (String.IsNullOrEmpty(this.ApplicationName))
{
this.ApplicationName = value;
}
}
}
public virtual IList<Membership> TheManyMemberships { get; protected set; }
}
public class User
{
public virtual Guid Id { get; set; }
public virtual Application TheApplication { get; set; }
public virtual Membership TheMembership { get; set; }
/* Scalar Properties of a User */
public virtual string UserName { get; set; }
}
public class Membership
{
private Guid UserId { get; set; }
private User _theUser { get; set; }
protected Membership() { }
public Membership(User theUser)
{
_theUser = theUser;
}
public virtual Application TheApplication { get; set; }
/* Scalar Properties of a Membership */
public virtual string Password { get; set; }
}
public class ApplicationMap : ClassMap<Application>
{
public ApplicationMap()
{
Table("aspnet_Applications");
Id(app => app.ApplicationId).Column("ApplicationId").GeneratedBy.GuidComb();
Map(x => x.ApplicationName );
Map(x => x.LoweredApplicationName);
Map(x => x.Description );
HasMany<Membership>(x => x.TheManyMemberships)
.Inverse()
.AsBag();
}
}
public class UserMap : ClassMap<User>
{
public UserMap()
{
Table("aspnet_Users");
Id(user => user.Id).Column("UserId").GeneratedBy.GuidComb();
References(x => x.TheApplication, "ApplicationId")
.Not.Nullable();
HasOne(x => x.TheMembership)
.Cascade.All();//
//.Constrained();
Map(x => x.UserName).Not.Nullable();
}
}
public class MembershipMap : ClassMap<Membership>
{
public MembershipMap()
{
Table("aspnet_Membership");
Id(Reveal.Member<Membership>("UserId"))
.GeneratedBy.Foreign("_theUser");
HasOne(
Reveal.Member<Membership, User>("_theUser"))
.Constrained()
.ForeignKey();
References<Application>(x => x.TheApplication, "ApplicationId")
.Not.Nullable();
Map(x => x.Password);
}
}
原谅一些命名约定,在原型设计时,我使用不明确的名称而不是正确的约定来避免混淆。
我有的DDL(来自上面的代码)和asp.net(4.0)的输出中的DDL(使用aspnet_regsql.exe构建DDL)似乎是一致的(两个版本之间)。
我要感谢这篇文章: http://brunoreis.com/tech/fluent-nhibernate-hasone-how-implement-one-to-one-relationship/
如果您进行任何调整,请发布。
但我能够保存应用程序,用户和会员资格。
但是,我认为我可能会稍微偏离用户:会员关系。 微软的场景似乎是“拥有一个用户,但允许该用户为每个应用程序设置不同的密码”,这是有道理的。 但有时当使用MembershipProvider代码时(MS代码,与NHibernate无关,我觉得“有时它会假设一个应用程序。”
我觉得MS DDL应该有一个独特的约束 dbo.Membership(UserId,ApplicationId),但我没有在他们的DDL中看到它。
无论如何,这应该提供一些思考的食物。
答案 1 :(得分:0)
您是否尝试过继承:
public class User
....
public class Member : User
....
你有什么理由加入ApplicationId吗?我相信它在两个表格中供参考。由于UserId是一个Guid,它是独一无二的。如果您确实遇到需要为两个不同的应用程序存储相同用户的情况,那么asp.net成员资格不能像那样工作,它会创建两个不同的用户记录。用户名/密码上的查找会根据Web应用程序设置(计算机密钥)检查应用程序ID,以启用其唯一性。会员表是一个红色的鲱鱼。