0

我正在使用Castle Active RecordNHibernate在MySql之上实现一个相对简单的用户管理模型,我遇到了一个问题。

比方说,我有两个表 _users_passwords以下 SQL create 语句描述

创建表 _users (
  id bigint(20) NOT NULL AUTO_INCREMENT,
  用户名 char(32) NOT NULL,
  主键(id),
  UNIQUE KEY username_UQ(用户名),
) 引擎=InnoDB 默认字符集=utf8;

创建表_密码(
  id bigint(20) NOT NULL AUTO_INCREMENT,
  creation_date datetime NOT NULL,
  user_id bigint(20) 非空,
  password_hash char(64) NOT NULL,
  valid_end_date datetime NOT NULL,
  主键(id),
  唯一键 user_id_password_UQ (user_id,password_hash),
  KEY user_passwords_FK (user_id),
  CONSTRAINT user_passwords_FK FOREIGN KEY (user_id) REFERENCES _users (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) 引擎=InnoDB 默认字符集=utf8;

这个想法是保留原始密码历史记录,因此,密码保存在单独的表 _passwords 中,该表与_users表具有多对一的关系。

现在,以下 C# 代码使用 Castle Active Records 对该结构进行建模

namespace DataEntities
{
    [ActiveRecord("_users")]
    public class User : ActiveRecordBase<User>
    {
        [PrimaryKey(PrimaryKeyType.Identity, "id", Access = PropertyAccess.NosetterLowercase)]
        public ulong Id
        {
            get;
            set;
        } // Id

        [Property("username", ColumnType = "String", NotNull = true, Unique = true)]
        [ValidateIsUnique]
        public string Username
        {
            get;
            set;
        } // Username

        [HasMany(typeof(Password))]
        public IList<Password> Passwords
        {
            get;
            set;
        } // Passwords

        public string ValidPasswordHash
        {
            get
            {
                DateTime l_dtNow = DateTime.Now;
                if (Passwords.Count != 1 || Passwords[0].ValidFrom >= l_dtNow || Passwords[0].ValidUntil <= l_dtNow)
                {
                    throw new Exception();
                }

                return Encoding.UTF8.GetString(Passwords[0].PasswordHash);
            }
        } // ValidPasswordHash

        public static User FindByCredentials(string i_sUsername, string i_sHashedPassword)
        {
            return FindOne(Restrictions.Eq("Username", i_sUsername), Restrictions.Eq("ValidPasswordHash", i_sHashedPassword));
        } // FindByCredentials
    } // User

    [ActiveRecord("_passwords")]
    public class Password : ActiveRecordBase<Password>
    {
        [PrimaryKey(PrimaryKeyType.Identity, "id", Access = PropertyAccess.NosetterLowercase)]
        public ulong Id
        {
            get;
            set;
        } // Id

        [BelongsTo("user_id", NotNull = true, UniqueKey = "_passwords_UQ1")]
        public ulong UserId
        {
            get;
            set;
        } // UserId

        [Property("password_hash", ColumnType = "UInt64", NotNull = true, UniqueKey = "_passwords_UQ1")]
        public byte[] PasswordHash
        {
            get;
            set;
        } // PasswordHash

        [Property("creation_date", ColumnType = "DateTime", NotNull = true)]
        public DateTime ValidFrom
        {
            get;
            set;
        } // ValidFrom

        [Property("valid_end_date", ColumnType = "DateTime", NotNull = true)]
        public DateTime ValidUntil
        {
            get;
            set;
        } // ValidUntil
    } // Password
} // DataEntities

并在我的应用程序启动框架被初始化

try
{
    ActiveRecordStarter.Initialize(ActiveRecordSectionHandler.Instance, typeof(Password),
                                                                        typeof(User));
}
catch (Exception l_excpt)
{
    // handle exception
}

最后,当这段代码运行时,它会生成以下异常:

Castle.ActiveRecord.Framework.ActiveRecordException:ActiveRecord 试图推断有关 User.Passwords 关系的详细信息,但在目标类型 DataEntities.Password 中找不到“BelongsTo”映射属性
   在 c:\daten\dev\External\Castle\AR2.0\ActiveRecord\Castle.ActiveRecord\Framework\Internal\Visitors\SemanticVerifierVisitor.cs:line 544 中的 Castle.ActiveRecord.Framework.Internal.SemanticVerifierVisitor.VisitHasMany(HasManyModel 模型)
   在 c:\daten\dev\External\Castle\AR2.0\ActiveRecord\Castle.ActiveRecord\Framework\Internal\Visitors\AbstractDepthFirstVisitor.cs:line 45 中的 Castle.ActiveRecord.Framework.Internal.AbstractDepthFirstVisitor.VisitNodes(IEnumerable 节点)
   在 c:\daten\dev\External\Castle\AR2.0\ActiveRecord\Castle.ActiveRecord\Framework\Internal\Visitors\AbstractDepthFirstVisitor.cs:line 59 中的 Castle.ActiveRecord.Framework.Internal.AbstractDepthFirstVisitor.VisitModel(ActiveRecordModel 模型)
   在 c:\daten\dev\External\Castle\AR2.0\ActiveRecord\Castle.ActiveRecord\Framework\Internal\Visitors\SemanticVerifierVisitor.cs:line 122 中的 Castle.ActiveRecord.Framework.Internal.SemanticVerifierVisitor.VisitModel(ActiveRecordModel 模型)
   在 c:\daten\dev\External\Castle\AR2.0\ActiveRecord\Castle.ActiveRecord\Framework\Internal\Visitors\AbstractDepthFirstVisitor.cs:line 45 中的 Castle.ActiveRecord.Framework.Internal.AbstractDepthFirstVisitor.VisitNodes(IEnumerable 节点)
   在 c:\daten\dev\External\Castle\AR2.0\ActiveRecord\Castle.ActiveRecord\Framework\ActiveRecordStarter.cs 中的 Castle.ActiveRecord.ActiveRecordStarter.RegisterTypes(ISessionFactoryHolder holder, IConfigurationSource source, IEnumerable`1 types, Boolean ignoreProblematicTypes) :第 927 行
   在 c:\daten\dev\External\Castle\AR2.0\ActiveRecord\Castle.ActiveRecord\Framework\ActiveRecordStarter.cs:line 202 中的 Castle.ActiveRecord.ActiveRecordStarter.Initialize(IConfigurationSource source, Type[] types)
   在 C:\Projects Code\xyz\Global.asax.cs:line 22 中的 Global.Application_Start(Object sender, EventArgs e)

好吧,我无休止地盯着班级的UserId财产Password,我用谷歌搜索过,现在我很迷茫。所以社区是我最后的希望......任何人都可以帮助我了解导致此异常的原因以及如何解决它?

提前感谢大家的回复和评论。

4

1 回答 1

1

您应该有一个User User { get; set; }引用属性而不是外键。

官方文档是一个很好的起点。

于 2012-11-19T02:24:29.670 回答