【问题标题】:"An invalid or incomplete configuration was used while creating a SessionFactory" NHibernate in Web Services“在 Web 服务中创建 SessionFactory 时使用了无效或不完整的配置”NHibernate
【发布时间】:2014-12-03 14:01:46
【问题描述】:

正如标题所说,我收到一条错误消息:“创建 SessionFactory 时使用了无效或不完整的配置。请检查 PotentialReasons 集合,并查看 InnerException 了解更多详细信息。”

我将从代码开始。

数据库:

用户表:

CREATE TABLE [dbo].[User] (
    [Id]           UNIQUEIDENTIFIER NOT NULL,
    [Username]     NVARCHAR (50)    NULL,
    [PasswordHash] CHAR (64)        NOT NULL,
    [Salt]         CHAR (64)        NOT NULL,
    [Role]         UNIQUEIDENTIFIER NOT NULL,
    [Token]        NVARCHAR (50)    NOT NULL,
    [TokenStamp]   DATETIME         NULL,
    CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED ([Id] ASC),
    CONSTRAINT [FK_User_Role] FOREIGN KEY ([Role]) REFERENCES [dbo].[Role] ([Id])
);

角色表:

CREATE TABLE [dbo].[Role] (
    [Id]   UNIQUEIDENTIFIER NOT NULL,
    [Name] NVARCHAR (50)    NULL,
    CONSTRAINT [PK_Role] PRIMARY KEY CLUSTERED ([Id] ASC)
);

用户类别:

using System;

    namespace Models
    {
        public class User : EntityBase
        {
            public virtual string Username { get; set; }
            public virtual string PasswordHash { get; set; }
            public virtual string Salt { get; set; }
            public virtual Guid Role { get; set; }
            public virtual string Token { get; set; }
            public virtual DateTime TokenStamp { get; set; }
        }
    }

角色类:

namespace Models
{
    public class Role : EntityBase
    {
        public virtual string Name { get; set; }
    }
}

实体库:

using System;

namespace Models
{
    public class EntityBase
    {
        public virtual Guid Id { get; set; }
    }
}

用户地图:

using FluentNHibernate.Mapping;
using Models;

namespace NHibernate.Mapping
{
    public class UserMap : ClassMap<User>
    {
        public UserMap()
        {
            Table("User");
            Id(x => x.Id).GeneratedBy.GuidComb();
            LazyLoad();
            References(x => x.Role).Column("Role");
            Map(x => x.Username).Column("Username");
            Map(x => x.PasswordHash).Column("PasswordHash").Not.Nullable();
            Map(x => x.Salt).Column("Salt").Not.Nullable();
            Map(x => x.Token).Column("Token").Not.Nullable();
            Map(x => x.TokenStamp).Column("TokenStamp");
        }
    }
}

角色映射:

using FluentNHibernate.Mapping;
using Models;

namespace NHibernate.Mapping
{
    public class RoleMap : ClassMap<Role>
    {
        public RoleMap()
        {
            Table("Role");
            Id(x => x.Id).GeneratedBy.GuidComb();
            LazyLoad();
            Map(x => x.Name).Column("Name");
        }
    }
}

CustomForeignKeyConvention:

using FluentNHibernate;
using FluentNHibernate.Conventions;

namespace NHibernate.Conventions
{
    public class CustomForeignKeyConvention : ForeignKeyConvention
    {
        protected override string GetKeyName(Member property, System.Type type)
        {
            if (property == null)
            {
                return type.Name;
            }

            return property.Name;
        }
    }
}

会话工厂:

using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using NHibernate.Conventions;

namespace NHibernate
{
    public static class SessionFactory
    {
        private static ISessionFactory _sessionFactory;

        public static ISessionFactory Instance
        {
            get
            {
                if (_sessionFactory == null)
                {
                    _sessionFactory = CreateSessionFactory();
                }

                return _sessionFactory;
            }
        }

        private static ISessionFactory CreateSessionFactory()
        {
            return Fluently.Configure()
                        .Database(MsSqlConfiguration.MsSql2012
                            .ConnectionString(c => c.FromConnectionStringWithKey("DatabaseConnectionString")))
                        .Mappings(m =>
                        {
                            m.FluentMappings.Conventions.AddFromAssemblyOf<CustomForeignKeyConvention>();
                            m.FluentMappings.AddFromAssemblyOf<Models.EntityBase>();
                        })
                        .BuildSessionFactory();
        }
    }
}

WebService.cs

using System.Linq;
using System.Net;
using System.Web.Services;
using NHibernate;
using Models;

[WebService(Namespace = "http://LambdAlarm.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

public class LambdAlarmWebService : WebService
{
    [WebMethod]
    public HttpStatusCode Login(string username, string password)
    {
        var factory = SessionFactory.Instance;
        var session = factory.OpenSession();
        var result = session.QueryOver<User>().List<User>();

        var login = result.Where(u => u.Username == username).Where(p => p.PasswordHash == password);

        return HttpStatusCode.NotFound;
    }
}

所以是的...这不是一件容易的事。我认为数据库中的外键关系与用户和角色表有一些关系。角色列应引用角色表中的 Id。

请帮忙!

【问题讨论】:

  • 你检查过收集的潜在原因吗?还是内部异常?大多数时候你会在那里得到你需要的一切
  • 它说:“{“来自表用户的关联引用了一个未映射的类:System.Guid”}”

标签: c# .net sql-server web-services nhibernate


【解决方案1】:

问题在于References() 是指引用另一个实体,而不是类型。如果你想使用一个类型,你应该使用Map(x =&gt; x.Role)而不是References(x =&gt; x.Role)

User 更改为:

public class User : EntityBase
{
    public virtual string Username { get; set; }
    public virtual string PasswordHash { get; set; }
    public virtual string Salt { get; set; }
    public virtual Role Role { get; set; } //CHANGED HERE
    public virtual string Token { get; set; }
    public virtual DateTime TokenStamp { get; set; }
}

还有你的UserMap

public UserMap()
{
    Table("User");
    Id(x => x.Id).GeneratedBy.GuidComb();
    LazyLoad();
    References(x => x.Role).Column("Role");
    Map(x => x.Username).Column("Username");
    Map(x => x.PasswordHash).Column("PasswordHash").Not.Nullable();
    Map(x => x.Salt).Column("Salt").Not.Nullable();
    Map(x => x.Token).Column("Token").Not.Nullable();
    Map(x => x.TokenStamp).Column("TokenStamp");
}

此外,当您使用 Fluent NHibernate 进行映射时,没有理由指定列名。默认情况下,它只会使用您的属性名称,因此 Map(x =&gt; x.Name).Column("Name").Not.Nullable() 之类的名称与 Map(x =&gt; x.Name).Not.Nullable() 相同

其他一些建议:

为您的映射创建一个基类以使其更容易:

public abstract class ClassMapBase<T> : ClassMap<T> where T: EntityBase
{
    protected ClassMapBase()
    {
        Id(x => x.Id).Not.Nullable().GeneratedBy.GuidComb();
        LazyLoad();
    }
}

另外,我很惊讶 NHibernate 没有在 EntityBase 上抱怨你的 Id 有一个公共设置器。它应该设置为受保护或私有。也无需指定您的表名,除非您希望它与您的实体名称不同

【讨论】:

    【解决方案2】:

    虽然有一个正确的答案,但我只会让其他人觉得有用的另一种解决方案。当您的应用程序无法访问您的数据库时,会导致此错误。所以:

    1. 签入services.exe 并查看您的 SQL Server 是否正在运行
    2. 或简单的解决方案,检查您的连接字符串是否指向您的数据库。

    【讨论】:

      【解决方案3】:

      如果其他人发现此类错误,请检查您的实体中是否存在 virtual 关键字。例如:

      public class Word : IEntity
      {
          public virtual int WordID { get; set; }
          public virtual string WordText { get; set; }
          public virtual string Pronunciation { get; set; }
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-10-24
        • 1970-01-01
        • 1970-01-01
        • 2012-11-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多