我正在尝试使用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));

我收到以下异常:

没有持久性:IdentityTest.Models.ApplicationUser

ApplicationUser类对IdentityUser没有任何其他属性(对于Asp.net Identity的Entity Framework实现,它可以正常工作)。

谁能提供有关如何使Asp.net身份与此NuGet包一起使用的建议?

最佳答案

我对这个库非常苦恼,这使我产生疑问,为什么这是将OWIN与NHibernate一起使用的推荐库。

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

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

transaction = session.BeginTransaction(IsolationLevel.ReadCommitted);

然后,您在transaction.Commit()中的操作完成执行后,需要调用AccountController,因此您将需要覆盖OnResultExecuted:
protected override void OnResultExecuted(ResultExecutedContext filterContext)
{
    transaction.Commit();
}

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

此外,即使解决了这些问题,该库也存在其他问题。我最终不得不从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;
}

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();
}

3)在NHibernate.AspNet.Identity.UserStore中:出于某种原因,至少在使用外部提供者(例如facebook)创建用户/用户登录名时,最初创建用户/用户登录名时,将调用Update方法而不是Add。/Create导致NHibernate尝试更新不存在的实体。现在,在不进行更多研究的情况下,在UserStore更新方法中,我将库的代码更改为在NHibernate session 上调用SaveOrUpdate而不是Update,从而解决了该问题。

我只对库进行了简单的测试,这些更改在更改后仍然有效,因此无法确定该库中还有多少其他运行时/逻辑错误。发现这些错误后,现在让我感到非常紧张。看起来,即使是简单的场景,也绝对没有进行任何测试。使用此库时要小心。

关于asp.net-mvc - 使用NHibernate.AspNet.Identity,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21243269/

10-12 12:42
查看更多