我已经使用.NET框架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包一起使用的建议?
解决方法
无论如何,为了回答您的问题,您提供的代码,您从github网站获得的图书馆的类添加了NHibernate映射. NHibernate没有ApplicationUser的映射,它只有一个基类的映射. NHibernate需要实例化类的映射.这是有问题的,因为您无法访问库的程序集中的映射代码,因此您不能将其更改为使用ApplicationUser类.所以唯一的办法就是使用库来实现,就是删除ApplicationUser类并使用库的IdentityUser类.或者,您可以复制github的映射代码,并尝试对ApplicationUser使用相同的映射.
此外,库代码及其给AccountController的代码并不会打开NHibernate事务,因此即使库调用Session.Save和Session.Update,数据也不会最终保存在数据库中.打开会话后,您需要打开一个事务并将其另存为该类的私有字段:
transaction = session.BeginTransaction(IsolationLevel.ReadCommitted);
那么你需要在AccountController中完成执行操作后调用transaction.Commit(),因此你需要重写OnResultExecuted:
protected override void OnResultExecuted(ResultExecutedContext filterContext) { transaction.Commit(); }
请记住,这个例子过于简单,在生产应用程序中,如果有错误,您需要检查您将Rollback而不是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)),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 /创建导致NHibernate尝试更新不存在的实体.现在,没有更多的看法,在UserStore更新方法中,我更改了库的代码,在NHibernate会话中调用SaveOrUpdate,而不是修复问题的Update.
我只是在我的更改之后对库进行了简单的测试,所以没有告诉这个库中有多少其他的运行时/逻辑错误.找到这些错误后,它现在使我非常紧张.似乎完全没有测试甚至简单的情况.请使用此图书馆小心.