使用NHibernate.AspNet.Identity

use*_*706 11 nhibernate asp.net-mvc asp.net-identity

我试图使用Asp.net身份和NHibernate.

我使用.NET framework 4.5.1创建了一个新的空白Asp.net MVC站点,我已经安装并遵循了使用nuget包NHibernate.AspNet.Identity的说明,如下所述:

https://github.com/milesibastos/NHibernate.AspNet.Identity

其中涉及对AccountController类的默认构造函数进行以下更改:

var mapper = new ModelMapper();
mapper.AddMapping<IdentityUserMap>();
mapper.AddMapping<IdentityRoleMap>();
mapper.AddMapping<IdentityUserClaimMap>();
mapper.AddMapping<IdentityUserLoginMap>();

var mapping = mapper.CompileMappingForAllExplicitlyAddedEntities();
var configuration = new Configuration();
configuration.Configure(System.Web.HttpContext.Current.Server.MapPath(@"~\Models\hibernate.cfg.xml"));
configuration.AddDeserializedMapping(mapping, null);

var schema = new SchemaExport(configuration);
schema.Create(true, true);

var factory = configuration.BuildSessionFactory();
var session = factory.OpenSession();

UserManager = new UserManager<ApplicationUser>(
                new UserStore<ApplicationUser>(session));
Run Code Online (Sandbox Code Playgroud)

我收到以下异常:

没有持久性:IdentityTest.Models.ApplicationUser

ApplicationUser类没有IdentityUser的任何其他属性(适用于Asp.net Identity的Entity Framework实现).

任何人都可以提供关于如何让Asp.net身份与这个NuGet包一起使用的建议吗?

wir*_*_in 20

我对这个库非常努力,这让我怀疑为什么这是推荐使用OWIN和NHibernate的库.

无论如何,为了回答你的问题,你从github网站获得的代码为库的类添加了NHibernate映射.NHibernate没有映射ApplicationUser,它只有一个映射它的基类.NHibernate需要实例化类的映射.这是有问题的,因为您无权访问库程序集中的映射代码,因此您无法将其更改为使用ApplicationUser该类.因此,使用库的唯一方法就是删除ApplicationUser类并使用库的IdentityUser类.或者,您可以从github复制映射代码并尝试使用相同的映射ApplicationUser.

此外,库代码和他为此提供的代码AccountController永远不会打开NHibernate事务,因此即使库调用Session.Save并且Session.Update数据最终也不会保存在数据库中.打开会话后,您需要打开一个事务并将其保存为类中的私有字段:

transaction = session.BeginTransaction(IsolationLevel.ReadCommitted);
Run Code Online (Sandbox Code Playgroud)

然后你需要transaction.Commit()AccountController完成执行后的动作后调用,所以你需要覆盖OnResultExecuted:

protected override void OnResultExecuted(ResultExecutedContext filterContext)
{
    transaction.Commit();
}
Run Code Online (Sandbox Code Playgroud)

请记住,此示例过于简单,在生产应用程序中,您需要进行错误检查,如果出现错误,您将回滚而不是提交,并且需要正确关闭/处理所有内容等.

此外,即使解决了这些问题,库也存在其他问题.我最终不得不从github下载源代码,所以我可以修改库以便使用它.库的代码中至少有3个其他明显的错误:

1)在NHibernate.AspNet.Identity.UserStore中:

public virtual async Task<TUser> FindAsync(UserLoginInfo login)
{
    this.ThrowIfDisposed();
    if (login == null)
        throw new ArgumentNullException("login");

    IdentityUser entity = await Task.FromResult(Queryable
        .FirstOrDefault<IdentityUser>(
            (IQueryable<IdentityUser>)Queryable.Select<IdentityUserLogin, IdentityUser>(
                Queryable.Where<IdentityUserLogin>(
                    // This line attempts to query nhibernate for the built in asp.net
                    // UserLoginInfo class and then cast it to the NHibernate version IdentityUserLogin, 
                    // which always causes a runtime error. UserLoginInfo needs to be replaced 
                    // with IdentityUserLogin
                    (IQueryable<IdentityUserLogin>)this.Context.Query<UserLoginInfo>(), (Expression<Func<IdentityUserLogin, bool>>)(l => l.LoginProvider == login.LoginProvider && l.ProviderKey == login.ProviderKey)),
                    (Expression<Func<IdentityUserLogin, IdentityUser>>)(l => l.User))));

    return entity as TUser;
}
Run Code Online (Sandbox Code Playgroud)

2)在NHibernate.AspNet.Identity.DomainModel.ValueObject中:

protected override IEnumerable<PropertyInfo> GetTypeSpecificSignatureProperties()
{
    var invalidlyDecoratedProperties =
        this.GetType().GetProperties().Where(
            p => Attribute.IsDefined(p, typeof(DomainSignatureAttribute), true));

    string message = "Properties were found within " + this.GetType() +
                                        @" having the
            [DomainSignature] attribute. The domain signature of a value object includes all
            of the properties of the object by convention; consequently, adding [DomainSignature]
            to the properties of a value object's properties is misleading and should be removed. 
            Alternatively, you can inherit from Entity if that fits your needs better.";

    // This line is saying, 'If there are no invalidly decorated properties, 
    // throw an exception'..... which obviously should be the opposite, 
    // remove the negation (!)
    if (!invalidlyDecoratedProperties.Any())
        throw new InvalidOperationException(message);

    return this.GetType().GetProperties();
}
Run Code Online (Sandbox Code Playgroud)

3)在NHibernate.AspNet.Identity.UserStore中:出于某种原因,至少在使用像facebook这样的外部提供程序创建用户/用户登录时,最初创建用户/用户登录时,将调用Update方法而不是Add /创建导致NHibernate尝试更新不存在的实体.现在,在没有进一步研究的情况下,在UserStore更新方法中,我更改了库的代码,以便SaveOrUpdate在NHibernate会话上调用而不是Update修复问题.

我只使用在我的更改后工作的库运行简单测试,因此无法知道此库中有多少其他运行时/逻辑错误.找到这些错误后,现在让我真的很紧张.即使是简单的场景,似乎也没有完成任何测试.请谨慎使用此库.

  • @Nate没有我没有在github上提交这些问题.我刚决定不使用它,因为它有很多问题. (2认同)
  • FWIW,看来您调出的每个项目都已在库中修复. (2认同)

Mar*_*den 5

我也很努力使用NHibernate.AspNet.Identity.我发现使用NHibernate创建自己的实现要容易得多,我在这里已经变成了一个最小的工作示例:

https://github.com/MartinEden/NHibernate.AspNet.Identity.Example

它们的关键部分是NHibernate会话的简单实现IUserStore<TUser, TKey>IUserPasswordStore<TUser, TKey>持久性.然后,只需要写一点胶水就可以告诉Owin使用该代码.